Используя struct в C #, как в C - не так ли? - PullRequest
2 голосов
/ 05 сентября 2011

Я читаю двоичный файл определенного формата, и я привык преобразовывать блок данных в структуру, а затем читать структуру, чтобы извлечь поля из двоичного файла данных.

Я пытаюсь это сделать, но в C # не получилось, они больше похожи на классы, чем на структуры в смысле C. Можно ли делать то, что я хочу? Например ..

public struct Datum {
    byte type;
    ushort payload;
}

public struct DiskPage {
    ushort pageNumber;
    Datum[] data = Datum[170];
}

Я хочу иметь возможность прочитать 512 байт файла и преобразовать его в DiskPage, а затем прочитать значения из структуры DiskPage. Это возможно в c # - или есть другой предпочтительный подход? Должен ли я просто оставить этот код в C и связать его?

Спасибо! Реза

Ответы [ 3 ]

4 голосов
/ 05 сентября 2011

Компилятор не учитывает порядок ваших полей по умолчанию (также он может перемещать поля и оставлять пробелы в памяти = Упаковка ). Используя StructLayout , вы можете применять другое поведение (по умолчанию, последовательное или явное).

Используйте MarshalAs для определенных опций на поле. Будьте осторожны с порядком байтов.

[StructLayout(LayoutKind.Explicit, Size=16, CharSet=CharSet.Ansi)]
public struct MySystemTime 
{
   [FieldOffset(0)]public ushort wYear; 
   [FieldOffset(2)]public ushort wMonth;
   [FieldOffset(4)]public ushort wDayOfWeek; 
   [FieldOffset(6)]public ushort wDay; 
   [FieldOffset(8)]public ushort wHour; 
   [FieldOffset(10)]public ushort wMinute; 
   [FieldOffset(12)]public ushort wSecond; 
   [FieldOffset(14)]public ushort wMilliseconds; 
}
3 голосов
/ 05 сентября 2011

Я предлагаю вам прочитать Освоение структур C # , в которых рассматривается использование маршалинга (в частности, Marshal.Copy) для этой цели.

0 голосов
/ 05 сентября 2011

Вы можете использовать фиксированные массивы в C #, если вы компилируете с включенной опцией Unsafe.Вы также можете использовать указатели.

internal unsafe struct MyStruct
{
    public fixed byte MyFixedArray[128];
    public byte* MyPointer;
}

Предпочтительно использовать маршаллинг, смещение поля и избегать небезопасного кода.Используйте небезопасный код, если вам действительно нужно слишком мало кода.Не открывайте внешнему миру фиксированный массив или указатель (интерфейсы или публичные классы \ структуры), если вы можете избежать этого.

...