Возможный дубликат:
Почему sizeof для структуры не равен сумме sizeof каждого члена?
Я пытался понять концепцию битовых полей.
Но я не могу найти, почему размер следующей структуры в CASE III составляет 8 байтов.
struct B
{
unsigned char c; // +8 bits
} b;
SizeOf (б); // Вывод: 1 (потому что беззнаковый символ занимает 1 байт в моей системе)
struct B
{
unsigned b: 1;
} b;
sizeof(b); // Output: 4 (because unsigned takes 4 bytes on my system)
struct B
{
unsigned char c; // +8 bits
unsigned b: 1; // +1 bit
} b;
sizeof(b); // Output: 8
Я не понимаю, почему вывод для случая III получается как 8. Я ожидал 1 (символ) + 4 (без знака) = 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.
Я думаю, что вы видите выравнивание эффект здесь.
Многие архитектуры требуют, чтобы целые числа сохранялись по адресам в памяти, кратным размеру слова.
Вот почему символ в вашей третьей структуре дополняется еще тремя байтами, так что следующее целое число без знака начинается с адреса, кратного размеру слова.
Char по определению является байтом. в 32-битной системе целые 4 байта. И структура дополняется дополнительными 4.
Увидеть http://en.wikipedia.org/wiki/Data_structure_alignment#Typical_alignment_of_C_structs_on_x86 для некоторого объяснения отступов
Чтобы сохранить выравнивание доступа к памяти, компилятор добавляет заполнение, если вы упакуете структуру, он не добавит дополнение.
Я еще раз взглянул на это, и вот что я нашел.
struct B { unsigned c: 8; unsigned b: 1; }b; printf("%lu\n", sizeof(b));
печать 4, которая является короткой;
Вы смешивали битовые поля с обычными элементами структуры.
Кстати, битовые поля определяются как: «набор смежных биты внутри блока хранения, определенного реализацией sindle. Итак, я даже не уверен, что ‘: 8’ делает то, что вы хотите. Казалось бы, это не в духе битовых полей (поскольку это уже не бит)
Выравнивание и общий размер структуры зависят от платформы и компилятора. Вы не можете не ожидать простых и предсказуемых ответов здесь. У компилятора всегда может быть какая-то особая идея. Например:
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% вероятности, что эти люди не будут знать о требованиях к выравниванию вашей структуры. Они даже не откроют ваш файл никогда.