Использование битовых полей C - PullRequest
4 голосов
/ 26 мая 2011

Мне нужно разобраться с некоторыми данными в следующей форме:

typedef struct{
    unsigned n1 : 12;
    unsigned n2 : 12;
    unsigned n3 : 12;
    unsigned n4 :  1;
    unsigned n5 : 35;
} data;

Я убедился, что в сумме они насчитывают до 9 байтов.
Но они не пишут.этой структуры в файл и ее чтение не восстанавливает все данные, и sizeof(data) возвращает 16.
В чем здесь проблема?

Ответы [ 4 ]

8 голосов
/ 26 мая 2011

Проблема в том, что компилятор добавляет некоторые отступы из соображений эффективности.

Это поведение может быть отменено.

Как это сделать с помощью gcc, см. Форсирование выравнивания в GCC

. Как это сделать с помощью Visual C ++:*

1 голос
/ 26 мая 2011

Вы можете использовать специфическое принудительное выравнивание для gcc:

typedef struct{
    unsigned n1 : 12;
    unsigned n2 : 12;
    unsigned n3 : 12;
    unsigned n4 :  1;
    unsigned n5 : 35;
} data __attribute__((__packed__));

Чтение: http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc/Type-Attributes.html

1 голос
/ 26 мая 2011

Ваша структура имеет длину 9 байт.Компилятор дополняет его до 16 байт, чтобы сделать его более дружественным к кешу.Это может быть отключено (я не рекомендую это вообще), используя специфичные для компилятора директивы / ключевые слова.См. выравнивание структуры данных .

0 голосов
/ 26 мая 2011

Это будет очень хорошо работать на 36-битном компьютере. Вы забыли сообщить нам, если это то, что вы получили ...

На более распространенной 32-битной машине использование 9-байтового выравнивания было бы очень трудно реализовать. Если вы создадите массив этих структур, вам потребуется другой код для доступа к полям в объекте с адресом по модулю 0 и с адресом по модулю 9.

12 битов первых трех полей должны быть получены из разных unsigned с и по-разному в зависимости от адреса.

Директивы упаковки в других ответах вряд ли сработают, если только у вас нет аппаратного обеспечения с битовой адресацией (или 36-битного ЦП).

...