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

Возможный дубликат:
Почему 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.

5

Решение

Вы можете проверить макет структуры с помощью 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.

7

Другие решения

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

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

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

3

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

Увидеть http://en.wikipedia.org/wiki/Data_structure_alignment#Typical_alignment_of_C_structs_on_x86 для некоторого объяснения отступов

2

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

1

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

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

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

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

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

1

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

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
По вопросам рекламы [email protected]