Размер структуры C ++: 2 + 4 + 2 + 2 + 4 = 16

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

Почему sizeof(); этой структуры 16 байт? Компилирую в g ++.

struct bitmapfileheader {       
     unsigned short bfType;
     unsigned int bfSize;
     unsigned short bfReserved1;
     unsigned short bfReserved2;
     unsigned int bfOffBits;   
   };

person Lukas    schedule 09.12.2009    source источник
comment
Dupe: stackoverflow.com/questions/119123/   -  person Michael Burr    schedule 09.12.2009
comment
en.wikipedia.org/wiki/Sizeof#Structure_padding   -  person    schedule 09.12.2009
comment
Кто сказал, что short - 2, а int - 4?   -  person Martin York    schedule 09.12.2009
comment
@Martin York он сказал, что использует g ++, и если он использует x86, то они будут 2 и 4 байта. Это очень большая вероятность ...   -  person Ramónster    schedule 09.12.2009
comment
После ответа на вопрос, если вам нечего добавить, я не понимаю, почему вы бросите туда еще один ответ «Я тоже». Ну давай же.   -  person marcc    schedule 09.12.2009


Ответы (9)


Это потому, что 4-байтовые целые числа выровнены по 4-байтовой границе, поэтому после bfType есть 2 байта заполнения.

person Ramónster    schedule 09.12.2009

Выравнивание. Скорее всего, на вашей платформе целые числа должны быть выровнены по 4 байта, а короткие - по 2 байта.

+0 -1 : bfType
+2 -3 : <padding>
+4 -7: bfSize
+8 -9: bfReserve1
+10 -11: bfReserve2
+12 -15: bfOffBits
-------------
16 bytes

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

person Sanjaya R    schedule 09.12.2009

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

Если вам это не нужно, вы можете использовать макрос UNALIGNED.

person Anon.    schedule 09.12.2009
comment
Я не думаю, что unaligned - ключевое слово. Это будет зависеть от компилятора. - person GManNickG; 09.12.2009
comment
Ответ хорош, но «unaligned» не является ключевым словом C ++. - person coppro; 09.12.2009
comment
В частности, в этом случае это выглядит как 2 байта заполнения перед первым int, чтобы выровнять его по 4-байтовой границе. Шорты выравниваются по 2-байтовым границам. - person Mark Ransom; 09.12.2009
comment
Ты прав. Правильный метод - использовать макрос UNALIGNED, который заменяется ключевым словом __unaligned для архитектур, чувствительных к выравниванию, или ничего в противном случае. Я отредактирую это в. - person Anon.; 09.12.2009
comment
В GCC вы можете использовать __attribute __ ((упаковано)); чтобы указать, что вы хотите отменить выравнивание полей. Например: беззнаковый короткий bfType __attribute __ ((упакованный)); - person Joey Adams; 09.12.2009
comment
Я почти уверен UNALIGNED, поскольку макрос тоже зависит от компилятора :) - person GManNickG; 09.12.2009
comment
__unaligned является расширением Visual C ++ и не поддерживается, например, g ++ (который в вопросе явно идентифицируется как используемая реализация). Любой такой макрос по своей сути зависит от реализации. - person Pavel Minaev; 09.12.2009
comment
Для выравнивания каждого элемента предъявляются минимальные требования (устанавливаются аппаратным обеспечением). Но компилятор может добавить еще больше отступов по другим причинам (например, для оптимизации). - person Martin York; 09.12.2009

Я думаю, ваш компилятор использует 4-байтовое выравнивание для полей.

person Andrew Lygin    schedule 09.12.2009

Эта проблема возникает из-за концепции, известной как выравнивание. Во многих случаях желательно иметь число, размещенное по адресу, который кратен размеру числа в байтах (до некоторого максимума, часто размера указателя платформы). Помещенная таким образом переменная называется выровненной по n-байтовой границе, где n - это число. Точные эффекты этого зависят от процессора. Многие процессоры выполняют математические вычисления быстрее, если данные правильно выровнены. Некоторые даже неспособны выполнять операции (иногда даже операции загрузки) с неподходящими выровненными данными - чтобы работать с такими данными, они должны быть загружены в два регистра, а затем необходимо выполнить серию битовых сдвигов и масок, чтобы получить полезное значение, а затем его нужно вернуть. Думайте об этом, как о хранении половины int в каждой из двух корзин и необходимости складывать их вместе, чтобы использовать ее, а не просто хранить все int в одной корзине.

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

Однако при компиляции в одной и той же системе заполнение, вероятно, будет согласованным, возможно, в зависимости от параметров компилятора и конкретного используемого ABI (как правило, вы в безопасности на той же платформе, если не пытаетесь сделать вещи несовместимыми). Вы можете свободно создать другую структуру с теми же первыми 5 членами, и они займут 16 байтов другой структуры в тех же самых позициях.

Если вам действительно нужно избежать такого поведения, вам придется проверить документацию к компилятору. Большинство компиляторов предлагают атрибут или ключевое слово, чтобы объявить переменную как не имеющую выравнивания, и еще один, чтобы указать, что структура не должна иметь отступов. Но это редко бывает необходимо в общем порядке.

person coppro    schedule 09.12.2009

U может прагма упаковать структуру, чтобы избежать заполнения

person tomkaith13    schedule 09.12.2009

ISO C ++ 03, 9.2 [class.mem] / 12:

Члены нестатических данных класса (не объединенного), объявленного без промежуточного спецификатора доступа, выделяются таким образом, чтобы более поздние члены имели более высокие адреса в объекте класса. Порядок распределения нестатических элементов данных, разделенных спецификатором доступа, не определен (11.1). Требования согласования реализации могут привести к тому, что два соседних элемента не будут размещены сразу после друг друга; так же могут быть требования к пространству для управления виртуальными функциями (10.3) и виртуальными базовыми классами (10.1).

person Pavel Minaev    schedule 09.12.2009

из-за способа выделения памяти после короткого

person Euclid    schedule 09.12.2009
comment
Действительно, это хорошее предложение. Однако приложение здесь относится к обработке файлов .bmp, так что это не вариант. +1 все равно ;-) - person Joey Adams; 09.12.2009

Это связано с выравниванием - компилятор должен сделать некоторые отступы.

person rmn    schedule 09.12.2009