Подтвердить что ты не робот

Почему размер этой структуры 24?

У меня есть структура, из которой я хочу рассчитать его размер:

#pragma pack(push,4)
struct  MyStruct
{  
    uint32_t i1;    /* size=4, offset=0. */
    uint32_t i2;    /* size =4 offset =4 */
    uint16_t s1;    /* size =2 offset=8 */
    unsigned char c[8]; /* size=8 offset=12*/
    uint16_t s2;    /* size=2 offset=20. */
    uint16_t s3;    /* size=2 offset=24. */

} ; // total size is 26 

static_assert(sizeof(MyStruct) == 24, "size of MyStruct incorrect");
#pragma pack(pop)

Статическое утверждение показывает, что размер 24, но мой расчет показывает, что он должен быть 26.

Почему размер 24?

Я работаю над Windows 7, 32-битным приложением, используя visual studio 2012

4b9b3361

Ответ 1

Выравнивание uint16_t равно 2, поэтому смещения:

#pragma pack(push,4)
struct  MyStruct
{  
    uint32_t i1;        /* offset=0  size=4 */
    uint32_t i2;        /* offset=4  size=4 */
    uint16_t s1;        /* offset=8  size=2 */
    unsigned char c[8]; /* offset=10 size=8 */
    uint16_t s2;        /* offset=18 size=2 */
    uint16_t s3;        /* offset=20 size=2 */
                        /* offset=22 padding=2 (needed to align MyStruct) */
} ; // total size is 24

Edit Наложение в конце необходимо для того, чтобы все элементы

MyStruct A[10]; // or
MyStruct*B = new MyStruct[10];

выравниваются соответствующим образом. Для этого требуется, чтобы sizeof(MyStruct) был кратным alignof(MyStruct). Здесь sizeof(MyStruct)= 6 * alignof(MyStruct).

Любой тип struct/class всегда добавляется к следующему краю его выравнивания.

Ответ 2

В дополнение к ответу Уолтера, подумайте о том, чтобы поймать эту рыбу самостоятельно. Все, что вам нужно, это функция printf и простая арифметика:

  struct MyStruct ms;

  printf("sizeof(ms): %zd\n", sizeof(ms));

  printf("i1\t%td\n", (uint8_t*)&ms.i1 - (uint8_t*)&ms);
  printf("i2\t%td\n", (uint8_t*)&ms.i2 - (uint8_t*)&ms);
  printf("s1\t%td\n", (uint8_t*)&ms.s1 - (uint8_t*)&ms);
  printf("c \t%td\n", (uint8_t*)&ms.c  - (uint8_t*)&ms);
  printf("s2\t%td\n", (uint8_t*)&ms.s2 - (uint8_t*)&ms);
  printf("s3\t%td\n", (uint8_t*)&ms.s3 - (uint8_t*)&ms);

(%zd предназначен для печати size_t, %td для печати ptrdiff_t. Простой %d, вероятно, будет работать отлично в большинстве систем.)

Вывод:

sizeof(ms): 24
i1      0
i2      4
s1      8
c       10
s2      18
s3      20

Ответ 3

4 4 2 8 2 2 - будет упакован как:

4 4 4 8 2 2 - последние два объединяются в 4 байта. третий элемент нуждается в дополнении, последний и последний - нет.