Во-первых, несмотря на то, что особенности заполнения оставлены на усмотрение компилятора, ОС также накладывает некоторые правила относительно требований выравнивания.В этом ответе предполагается, что вы используете gcc, хотя ОС может различаться
Чтобы определить пространство, занимаемое данной структурой и ее элементами, вы можете следовать следующим правилам:
Сначала предположим, чтоСтруктура всегда начинается с адреса, который правильно выровнен для всех типов данных.
Затем для каждой записи в структуре:
- Минимальное необходимое пространство - этонеобработанный размер элемента, заданный
sizeof(element)
. - Требование выравнивания элемента является требованием выравнивания базового типа элемента.Примечательно, что это означает, что требование выравнивания для массива
char[20]
такое же, как требование для простого char
.
Наконец, требование выравнивания структуры в целом является максимальнымтребований к выравниванию каждого из его элементов.
gcc вставит заполнение после заданного элемента, чтобы гарантировать, что следующий (или структура, если мы говорим о последнем элементе) правильно выровнен. никогда не изменит порядок элементов в структуре, даже если это сэкономит память.
Теперь сами требования к выравниванию также немного странны.
- 32-битный Linux требует, чтобы 2-байтовые типы данных имели 2-байтовое выравнивание (их адреса должны быть четными).Все большие типы данных должны иметь 4-байтовое выравнивание (адреса, оканчивающиеся на
0x0
, 0x4
, 0x8
или 0xC
).Обратите внимание, что это относится и к типам, размер которых превышает 4 байта (например, double
и long double
). - 32-битная Windows более строгая в том смысле, что если тип имеет размер K байтов, он долженбыть выровненным по байту.Это означает, что
double
можно разместить только по адресу, оканчивающемуся на 0x0
или 0x8
.Единственное исключение из этого - long double
, который по-прежнему выровнен по 4 байта, хотя на самом деле он имеет длину 12 байтов. - Для Linux и Windows на 64-битных машинах тип K байтов долженбыть выровненным по байту.Опять же,
long double
является исключением и должно быть выровнено в 16 байт.