Размер структуры, отступы и будущее

Рассмотрим следующую программу

#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 функция для вывода сообщения и выхода, если они не верны. Это не повлияет на код в поле, но очень поможет, если вы перейдете к компилятору с более строгими выравниваниями.

И это тот момент, когда вы меняете его (см. ЯГНИ). Проблема с планированием всех возможных вариантов будущего заключается в том, что вы понятия не имеете, что произойдет:-)

Будущее... Пока вы можете использовать #pragma pack(1)

Другие вопросы по тегам