Оператор sizeof возвращает неверный размер?

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

По какой-то причине sizeof Оператор возвращает фиктивный размер для этой структуры (48 вместо 40):

typedef struct mbdb_file_info {
  uint16_t mode;

  uint32_t unk0;
  uint32_t unk1;
  uint32_t user_id;
  uint32_t group_id;

  uint32_t time0;
  uint32_t time1;
  uint32_t time2;

  uint64_t length;
  uint8_t flag;
  uint8_t property_count;
} mbdb_file_info;

Итак, вот простой тест:

printf("%ld %ld %ld %ld: %ld", sizeof(uint8_t),
                                sizeof(uint16_t), 
                                sizeof(uint32_t),
                                sizeof(uint64_t),
                                sizeof(mbdb_file_info));

Какие отпечатки:

1 2 4 8: 48

Как это произошло? Если вы сложите все размеры вместе, вы получите 40 не 48, Где на земле 48 родом из?

И если это странно x86-64 perk, как я могу гарантировать, что все поля структур занимают суммы, которые я хочу, чтобы они занимали (я бросаю кучу байтов в эту структуру)?

5 ответов

Решение

Компилятор может добавить несколько байтов в середине структуры, чтобы выровнять члены структуры. Размер структуры, по крайней мере, является суммой размера членов, но не ограничивается этим.

Вы также можете избавиться от отступов, переупорядочив элементы структуры. Например, если вы объявляете 64-битные, 32-битные, 16-битные, 16-битные, то 8-е, это будет естественно выровнено и не будет иметь дополнительных байтов заполнения.

Из-за структуры дополнения (не уверен, какой термин был здесь). Самое большое поле - 64-битное, поэтому все выровнено по нему. Итак, имеем:

typedef struct mbdb_file_info {
  uint16_t mode; // 16 + 

  uint32_t unk0; // 32 = 48, so add 16 more to align to 64bit;
  uint32_t unk1; // this
  uint32_t user_id; // and this give 64bits ;
  uint32_t group_id; // again this

  uint32_t time0; // plus this - 64bits;
  uint32_t time1; // this 
  uint32_t time2; // and this = 64bit ;

  uint64_t length; // this is 64 by itself
  uint8_t flag;  // this
  uint8_t property_count; // +this is 16, add 48 for the alignment
} mbdb_file_info; // when you sum all bits (+ the additional for padding)
                      // you have exactly 48B

Выравнивание. Некоторые типы данных выровнены по определенным границам (читай: адреса, делимые на коэффициент 2, например, 16), в зависимости от архитектуры, и это вызывает заполнение структуры.

Есть опции компилятора, чтобы подавить это поведение, и документация gcc говорит вам, как использовать aligned атрибут для этого.

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

Вероятно, что 8- и 16-битные значения дополняются до 32-битных, а вся структура дополняется кратным размеру машинного слова (8).

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