Размер структур в .NET - PullRequest
       23

Размер структур в .NET

9 голосов
/ 11 марта 2010

Моя проблема состоит в том, чтобы отправить структуру между программой на C в программу на C #.

Я сделал структуру в C #:

public struct NetPoint {
    public float lat; // 4 bytes
    public float lon; // 4 bytes
    public int alt; // 4 bytes
    public long time; // 8 bytes
}

Общий размер структуры должен составлять 20 байтов.

Когда я делаю sizeof() в C ++ этой структуры,

System.Diagnostics.Debug.WriteLine(
    "SizeOf(NetPoint) = " +
    System.Runtime.InteropServices.Marshal.SizeOf(new NetPoint()));

консоль отладки показывает:

SizeOf (NetPoint) = 24

Но я ожидал иметь 20 байтов. Почему я вижу разницу?

Ответы [ 4 ]

9 голосов
/ 11 марта 2010

Как правило, процессоры предпочитают, чтобы переменные выравнивались в памяти в месте, кратном их размеру, поэтому четырехбайтовое целое число должно быть в адресе памяти, который делится на четыре, и на восемь байт long должен находиться по адресу, кратному восьми.

Разработчики языка C # (и C ++) знают это, и они будут вставлять отступы в структуры для обеспечения необходимого выравнивания. Таким образом, фактическое расположение вашей структуры выглядит следующим образом:

public struct NetPoint {
    public float lat;          // 4 bytes   Offset  0
    public float lon;          // 4 bytes   Offset  4
    public int alt;            // 4 bytes   Offset  8
    int to_preserve_alignment; // 4 bytes   Offset 12
    public long time;          // 8 bytes   Offset 16
}

Вы можете исправить это, сделав long первым значением, как правило, если вы всегда помещаете самые большие значения в начало ваших структур, у вас не будет вставлен отступ для сохранения выравнивания элементов.

Вы также можете исправить это, добавив

[StructLayout(LayoutKind.Sequential, Pack = 4)]

до объявления структуры, но это приведет к неправильному выравниванию long time, что снижает производительность. На некоторых процессорах это сильно снижает производительность. (Например, ALPHA AXP будет неисправен для смещенных элементов). x86 Процессоры имеют лишь незначительное снижение производительности, но существует опасность того, что будущие процессоры будут иметь значительное снижение производительности, поэтому лучше, если вы можете, правильно спроектировать свои структуры (а не упаковывать их). 1017 *

7 голосов
/ 11 марта 2010

На самом деле технически структура должна иметь размер минимум из 20 байтов. Если вы выделите больше при отправке, получатель просто не будет использовать / копировать их. Проблема всегда в нераспределении.

Тем не менее, я вижу проблему. Хм. Я думаю, что проблема в последнем длинном .... который ИМХО выравнивается до восьми байтов, вставляя четыре пустых байта раньше. Я думаю, что есть потеря производительности за то, что восьмибайтовый элемент не выровнен по восьмибайтовой границе.

Attach StructLayout атрибутов для определения смещения каждого элемента вручную. Тогда вы сможете привести все в порядок.

Ссылка: Как управлять физическим макетом полей данных в .NET Framework 2.0

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct NetPoint {  
    public float lat; // 4 bytes 
    public float lon; // 4 bytes 
    public int alt; // 4 bytes 
    public long time; // 8 bytes 
} 

Это, по крайней мере, должно выровнять элементы по однобайтовой границе. Вы можете пойти дальше, определив точное начало каждого элемента, если необходимо.

2 голосов
/ 11 марта 2010

Попробуйте добавить атрибут [StructLayout (LayoutKind.Sequential, Pack = 1)] и посмотрите, что произойдет. Я подозреваю, что заполнение 8 байтов, так что это 3x8 байтов.

1 голос
/ 11 марта 2010

TomTom ответил на этот вопрос довольно хорошо, я думаю, но есть и другая альтернатива, если вы окажетесь в сложной ситуации со структурой взаимодействия COM. Каждое поле может быть выровнено отдельно с использованием атрибутов FieldOffset.

[StructLayout(LayoutKind.Explicit)]
public struct COMPoint
{
    [FieldOffset(0)] public int X;
    [FieldOffset(4)] public int Y;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...