Размер структуры, отступы и будущее
Рассмотрим следующую программу
#include <cstdio>
#include <stdint.h>
struct Foo
{
int32_t a;
int32_t b;
int32_t c;
};
struct Bar
{
int32_t a;
int32_t b;
int16_t c;
};
int main()
{
printf("sizeof(Foo)=%u\nsizeof(Bar)=%u",sizeof(Foo),sizeof(Bar));
return 0;
}
При компиляции с использованием MinGW я получаю sizeof(Foo)=12 и sizeof(Bar)=12 в 32-битной и 64-битной системах (я полагаю, что в 16-битной среде sizeof(Bar)=10). Вполне вероятно, что в будущем размер этих структур будет 16, чтобы лучше соответствовать в 64-битной среде?
Я храню структуры в файлах и не хочу добавлять обходные пути в будущем. Схема структуры вещей Doom была хорошим выбором в 1993 году, но не сегодня.
2 ответа
Размер Bar
Структура имеет мало общего с тем, находитесь ли вы в 16-битной среде, она имеет отношение исключительно к требованиям выравнивания полей в вашей структуре.
Выравнивание структуры обычно идентично наиболее ограничивающему выравниванию всех полей в ней. В данном случае это требование 32-битного выравнивания int32_t
Тип, который влияет на это.
Теперь вы можете подумать, что это не должно быть так, поскольку поле final является 16-битным значением и после него ничего не требуется, но вы ошибаетесь. Подумайте, что происходит с массивом этих вещей:
0000 index 0 a 32 bits
0004 b 32 bits
0008 c 16 bits
000a filler 16 bits
000c index 1 a 32 bits
0010 b 32 bits
0014 c 16 bits
0018 filler 16 bits
Вы можете видеть, что наполнитель требуется после c
в связи с требованием следующего a
быть правильно выровненным.
С точки зрения будущего, маловероятно, что какое-либо выравнивание этих полей изменится просто потому, что они являются точными типами битовой ширины. Они всегда будут 32-битными значениями и, вероятно, всегда требуют 32-битного выравнивания.
Сказав это, нет гарантии, что вы не найдете реализацию, которая требует, чтобы 32-битные значения были выровнены по 128-битным границам в будущем. Раздел 6.2.8 Alignment of objects
является управляющим разделом в C11, и, похоже, он не исключает эту возможность, поскольку не указывает, что выравнивание связано с размером объекта:
Тип объекта налагает требование выравнивания на каждый объект этого типа: более строгое выравнивание может быть запрошено, используя
_Align
ключевое слово.
Если вы хотите уловить возможность изменения размера и / или выравнивания структуры, вы можете использовать sizeof
а также alignof
в вашем main
функция для вывода сообщения и выхода, если они не верны. Это не повлияет на код в поле, но очень поможет, если вы перейдете к компилятору с более строгими выравниваниями.
И это тот момент, когда вы меняете его (см. ЯГНИ). Проблема с планированием всех возможных вариантов будущего заключается в том, что вы понятия не имеете, что произойдет:-)