Размер структуры, содержащей битовые поля

Возможный дубликат:
Почему sizeof для структуры не равен сумме sizeof каждого члена?

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

СЛУЧАЙ I:

struct B    
{
    unsigned char c;  // +8 bits
} b;

SizeOf(б); // Вывод: 1 (потому что беззнаковый символ занимает 1 байт в моей системе)

СЛУЧАЙ II:

struct B
{
    unsigned b: 1;
} b;

 sizeof(b); // Output: 4 (because unsigned takes 4 bytes on my system)

СЛУЧАЙ III:

struct B
{
    unsigned char c;  // +8 bits
    unsigned b: 1;    // +1 bit
} b;

sizeof(b); // Output: 8 

Я не понимаю, почему вывод для случая III получается как 8. Я ожидал 1 (символ) + 4(без знака) = 5.

6 ответов

Решение

Вы можете проверить макет структуры с помощью offsetof, но это будет что-то вроде:

struct B
{
    unsigned char c;  // +8 bits
    unsigned char pad[3]; //padding
    unsigned int bint; //your b:1 will be the first byte of this one
} b;

Теперь очевидно, что (в 32-битной арке) sizeof(b) будет 8не так ли?

Вопрос в том, почему 3 байта заполнения, а не более или менее?

Ответ заключается в том, что смещение поля в структуре имеет те же требования к выравниванию, что и тип самого поля. В вашей архитектуре целые числа выровнены по 4 байта, поэтому offsetof(b, bint) должно быть кратным 4. Это не может быть 0, потому что есть c раньше, так будет 4. Если поле bint начинается со смещения 4 и имеет длину 4 байта, затем размер структуры равен 8.

Другой способ взглянуть на это состоит в том, что требование выравнивания структуры является самым большим из всех ее полей, так что это B будет выровнен по 4 байта (так как это ваше битовое поле). Но размер типа должен быть кратным выравниванию, 4 недостаточно, поэтому будет 8.

Я думаю, что вы видите эффект выравнивания здесь.

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

Вот почему символ в вашей третьей структуре дополняется еще тремя байтами, так что следующее целое число без знака начинается с адреса, кратного размеру слова.

Char по определению является байтом. В 32-битной системе значения int составляют 4 байта. И структура дополняется дополнительными 4.

См. http://en.wikipedia.org/wiki/Data_structure_alignment для некоторых объяснений заполнения

Выравнивание и общий размер структуры зависят от платформы и компилятора. Вы не можете не ожидать простых и предсказуемых ответов здесь. У компилятора всегда может быть какая-то особая идея. Например:

struct B
{
    unsigned b0: 1;    // +1 bit
    unsigned char c;  // +8 bits
    unsigned b1: 1;    // +1 bit
};

Компилятор может объединять поля b0 и b1 в одно целое число и не может. Это зависит от компилятора. У некоторых компиляторов есть ключи командной строки, которые управляют этим, у некоторых нет. Другой пример:

struct B
{
    unsigned short c, d, e;
};

Компилятор должен упаковать / не упаковать поля этой структуры (при условии 32-битной платформы). Структура структуры может отличаться между сборками DEBUG и RELEASE.

Я бы рекомендовал использовать только следующий шаблон:

struct B
{
    unsigned b0: 1;
    unsigned b1: 7;
    unsigned b2: 2;
};

Если у вас есть последовательность битовых полей, которые имеют один и тот же тип, компилятор поместит их в один тип int. В противном случае могут возникнуть различные аспекты. Также учтите, что в большом проекте вы пишете кусок кода, а кто-то другой будет писать и перезаписывать make-файл; переместите свой код из одной библиотеки в другую. На этом этапе флаги компилятора будут установлены и изменены. 99% вероятности, что эти люди не будут знать о требованиях к выравниванию вашей структуры. Они даже не откроют ваш файл никогда.

Чтобы сохранить доступ к памяти выровненным, компилятор добавляет заполнение, если вы упакуете структуру, он не добавит дополнение.

Я еще раз взглянул на это, и вот что я нашел.

  1. Из книги C: "Почти все в полях зависит от реализации".
  2. На моей машине:
 struct B {
    unsigned c: 8;
    unsigned b: 1;
}b;
printf("%lu\n", sizeof(b));

печать 4, которая является короткой;

Вы смешивали битовые поля с обычными элементами структуры.

Кстати, битовые поля определены как: "набор смежных битов в блоке хранения, заданном реализацией sindle". Итак, я даже не уверен, что ':8' делает то, что вы хотите. Казалось бы, это не в духе битовых полей (поскольку это уже не бит)

Другие вопросы по тегам