Почему размер моего союза больше, чем я ожидал? - PullRequest
7 голосов
/ 27 августа 2011

Когда я печатаю размер союза следующим образом:

union u {
  char c[5];
  int i;
} un;

используя это:

int _tmain(int argc, _TCHAR* argv[])
{
    printf("size of union = %d ",sizeof(un));
    return 0;
}

Я получаю ответ 8 с использованием Visual C ++, но ожидал 5. Почему?

Ну, для того же примера, я сделал что-то вроде этого:

int i1 = 0x98761234;
un.i = i1;
printf("\n un.c[0] = %x ",un.c[0]);
printf("\n un.c[1] = %x ",un.c[1]);
printf("\n un.c[2]= %x ",un.c[2]);
printf("\n un.c[3] = %x ",un.c[3]);
printf("\n un.c[4] = %x ",un.c[4]);
printf("size of union = %d ",sizeof(un));

Я получил такие результаты, как

un.c[0] = 34;
un.c[1] = 12;
un.c[2] = 76;
un.c[3] = ffffff98;

почему в un.c есть 6fs [3]

Ответы [ 5 ]

11 голосов
/ 27 августа 2011

Оператор sizeof создает размер переменной или типа, включая любой отступ, необходимый для разделения элементов в массиве этого типа, так что все по-прежнему правильно выровнено. Поскольку ваш союз имеет член int, он должен быть выровнен на 4 байта, поэтому его «естественный» размер округляется в большую сторону до следующего кратного 4 байта.


ffffff98 потому что вы компилируете со знаком char. Использование %x с аргументом, который не является unsigned int, вызывает неопределенное поведение; то, что вы видите, иногда называется знак-расширение . Результат вашего псевдонима 0x98 интерпретируется как char, то есть -104. Это сохраняет свое значение при повышении до int (это называется повышением аргумента по умолчанию ), и int -104, когда псевдоним unsigned int, становится 0xffffff98.

3 голосов
/ 26 сентября 2014

enter image description here Компилятор добавляет несколько байтов для выравнивания

3 голосов
/ 27 августа 2011

Выравнивание вашего союза должно быть наибольшим выравниванием любого из его членов.Это 4. Следовательно, размер объединения должен соответствовать этому размеру.Это может быть 5 (поскольку c является самым крупным членом объединения), но поскольку выравнивание объединения в целом равно 4, размер объединения дополняется до 8.

Обратите внимание, чтоэто только для VC ++.Стандарт конкретно не требует этого.Хотя это позволяет реализациям заполнять типы по мере необходимости, что делает VC ++.GCC может сделать что-то другое, и могут быть переключатели времени компиляции, которые вы могли бы использовать для изменения этого поведения.

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

Компилятор может добавлять отступы, где он хочет, к структурам, объединениям и классам для ускорения доступа к памяти.Вы видите эффект этого.В Visual C ++ заполнение обычно кратно размеру наибольшего типа элемента.В этом случае самый большой член - int, поэтому он объединяет объединение 3 неиспользуемыми байтами, чтобы получить общий размер 8.

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

Спасибо за ваши предложения. Я попробовал это с множеством примеров и выглядит, что размер объединения эквивалентен (размер элемента max) + отступ (в зависимости от размера самого большого используемого типа данных).

...