Страницы

Поиск по вопросам

воскресенье, 15 декабря 2019 г.

Аналог структуры C++ с битовыми полями в C#

#c_sharp #cpp #struct


Объясните, выделяется размер для следующей структуры

struct BURInSyncStruct
{
    uint16_t Sync1 : 12;
    uint16_t Sync2 : 12;
    uint16_t Sync3 : 12;
    uint16_t Sync4 : 12;
} __attribute__((packed));


и как записать такую структуру на C#? Я пытался записать следующим образом 

[StructLayout(LayoutKind.Explicit)]
struct BURInSyncStruct
{
    [FieldOffset(0)]
    public ushort Sync1;
    [FieldOffset(1)]
    public ushort Sync2;
    [FieldOffset(2)]
    public ushort Sync3;
    [FieldOffset(3)]
    public ushort Sync4;
} 


но, мне кажется, это не верно.   
    


Ответы

Ответ 1



Естественно, это неверно. В С++ 4 битовых поля по 12 бит, расположенных вплотную без пропусков ( __attribute__((packed))). В вашем объявлении для С# 4 обыкновенных поля ushort, накладывающихся друг на друга. Как сделать правильно? В C# нет битовых полей, но есть класс BitConverter и битовые операции, которые позволяют реализовать их. Битовые маски для установки полей Sync1 и Sync2 выглядят так: Байт №: | 5| 4| 3| 2| 1| 0| 00001111 11111111 = 0x0FFF Sync1 Байт №: | 5| 4| 3| 2| 1| 0| 11111111 11110000 00000000 = 0xFFF000 Sync2 Это приводит нас к такому коду: [StructLayout(LayoutKind.Sequential)] public struct BURInSyncStruct { public static BURInSyncStruct Create() { BURInSyncStruct s = new BURInSyncStruct(); s.data = new byte[6]; return s; } [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] data; public ushort Sync1 { get { byte[] bytes64 = new byte[8]; Array.Copy(data, bytes64, data.Length); ulong x = BitConverter.ToUInt64(bytes64, 0); ulong y = x & 0x0FFF; return (ushort)y; } set { byte[] bytes64 = new byte[8]; Array.Copy(data, bytes64, data.Length); ulong x = BitConverter.ToUInt64(bytes64, 0); x = x & ~((ulong)0x0FFF); ulong y = (ulong)value & 0x0FFF; ulong res = x | y; bytes64 = BitConverter.GetBytes(res); Array.Copy(bytes64, data, data.Length); } } public ushort Sync2 { get { byte[] bytes64 = new byte[8]; Array.Copy(data, bytes64, data.Length); ulong x = BitConverter.ToUInt64(bytes64, 0); ulong y = x & 0xFFF000; y = y >> 12; return (ushort)y; } set { byte[] bytes64 = new byte[8]; Array.Copy(data, bytes64, data.Length); ulong x = BitConverter.ToUInt64(bytes64, 0); x = x & ~((ulong)0xFFF000); ulong y = (ulong)(value << 12) & 0xFFF000; ulong res = x | y; bytes64 = BitConverter.GetBytes(res); Array.Copy(bytes64, data, data.Length); } } }

Комментариев нет:

Отправить комментарий