Как размер этой структуры получается 4 байта - PullRequest
2 голосов
/ 19 августа 2011

У меня есть структура, в которой есть битовые поля. По моему мнению, она составляет 2 байта, но она равна 4. Я прочитал некоторые вопросы, связанные с этим здесь, в stackoverflow, но не в состоянии относиться кМоя проблема. Это структура, у меня действительно есть

struct s{
char b;
int c:8;
};
int main()
{
printf("sizeof struct s = %d bytes \n",sizeof(struct s));
return 0;
}

, если тип int должен находиться на границе памяти, тогда вывод должен быть 8 байтов, но он показывает 4 байта ??

Ответы [ 5 ]

1 голос
/ 19 августа 2011

enter image description here

Источник: http://geeksforgeeks.org/?p=9705

В сумме: оптимизирует упаковку битов (для этого предназначены битовые поля) как можно больше.без ущерба для выравнивания.

Выравнивание данных переменной связано с тем, как данные хранятся в этих банках.Например, естественное выравнивание int на 32-битной машине составляет 4 байта.Когда тип данных выровнен естественным образом, центральный процессор выбирает его в минимальных циклах чтения.

Аналогично, естественное выравнивание short int составляет 2 байта.Это означает, что короткий int может храниться в паре банк 0 - банк 1 или пара банк 2 - банк 3.double требует 8 байтов и занимает две строки в банках памяти.Любое смещение double приведет к тому, что более двух циклов чтения приведет к получению двойных данных.

Обратите внимание, что двойная переменная будет размещена на границе 8 байтов на 32-битной машине и требует двух циклов чтения из памяти.На 64-битной машине, основанной на количестве банков, двойная переменная будет размещена на границе 8 байт и требует только один цикл чтения из памяти.

Таким образом, компилятор введет требование выравнивания для каждой структуры.Это будет как у самого крупного члена структуры.Если вы удалите char из вашего struct, вы все равно получите 4 байта .

В вашем struct, char выровнено на 1 байт.За ним следует битовое поле int, которое выровнено на 4 байта для целых чисел, но вы определили битовое поле.

8 бит = 1 байт.Char может быть любой байтовой границей.Итак Char + Int:8 = 2 байта.Ну, это нечетная граница байтов, поэтому компилятор добавляет дополнительные 2 байта для поддержки 4-байтовой границы.

Чтобы она была 8 байтов, вам нужно было бы объявить фактическую int (4 байта)и char (1 байт).Это 5 байтов.Ну, это еще одна нечетная граница байтов, поэтому struct дополняется до 8 байтов .

В прошлом я обычно делал, чтобы контролировать заполнение, чтобы поместить заполнители между моими struct, чтобы всегда поддерживать 4-байтовую границу.Поэтому, если у меня есть struct, как это:

struct s {
    int id;
    char b;
};

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

struct d {
    int id;
    char b;
    char temp[3];
}

Это даст мне struct с размером4 байта + 1 байт + 3 байта = 8 байт!Таким образом, я могу гарантировать, что мой struct дополнен так, как я хочу, особенно если я передаю его куда-нибудь по сети.Кроме того, если я когда-нибудь изменю свою реализацию (например, если бы мне нужно было сохранить этот struct в двоичный файл, заполнители были там с самого начала и до тех пор, пока я поддерживаю свою первоначальную структуру,все хорошо!)

Наконец, вы можете прочитать этот пост на C Размер структуры с битовыми полями для более подробного объяснения.

1 голос
/ 19 августа 2011

int c:8; означает, что вы объявляете bit-field размером 8 бит.Так как выравнивание в 32-битных системах обычно составляет 4 байта (= 32 бита), ваш объект будет иметь 4 байта вместо 2 байтов (символ + 8 бит).

0 голосов
/ 19 августа 2011

В общем, независимом от платформы C вы никогда не узнаете ни размер структуры / объединения, ни размер битового поля. Компилятор может добавлять столько байтов заполнения, сколько ему угодно в любом месте внутри структуры / объединения / битового поля, за исключением самой первой ячейки памяти.

Кроме того, компилятор также может добавлять любое количество заполнителей битов в битовое поле и может помещать их в любое удобное для него место, потому что какой бит равен msb, а lsb не определяется C .

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

Разумное решение состоит в том, чтобы никогда не использовать битовые поля, они являются избыточной функцией C. Вместо этого используйте побитовые операторы. Битовые операторы и подробные документированные битовые поля будут генерировать один и тот же машинный код (недокументированные битовые поля могут приводить к совершенно произвольному коду). Но побитовые операторы гарантированно работают одинаково на любом компиляторе / системе в мире.

0 голосов
/ 19 августа 2011

Они выравнивание полей в структуре зависит от компилятора / платформы.Может быть, ваш компилятор использует 16-битные целые числа для битовых полей длиной меньше или равной 16 битам, возможно, он никогда не выравнивает структуры на чем-либо меньшем, чем 4-байтовая граница.Поля структуры выровнены, вам следует прочитать документацию по используемому компилятору и платформе.

0 голосов
/ 19 августа 2011

Но если вы укажете, что c должен занимать 8 бит, это не совсем int, не так ли?Размер c + b составляет 2 байта, но ваш компилятор дополняет структуру до 4 байтов.

...