gcc 4.3.4 ошибка с размером структуры? - PullRequest
0 голосов
/ 28 декабря 2011

Что не так с этим кодом, когда я компилирую его с -DPORTABLE?

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    unsigned char data[11];

#ifdef PORTABLE
    unsigned long intv;
#else
    unsigned char intv[4];
#endif

} struct1;

int main() {

    struct1 s;

    fprintf(stderr,"sizeof(s.data) = %d\n",sizeof(s.data));
    fprintf(stderr,"sizeof(s.intv) = %d\n",sizeof(s.intv));
    fprintf(stderr,"sizeof(s) =      %d\n",sizeof(s));

    return 0;
}

Вывод, который я получаю на 32-битном GCC:

$ gcc -o struct struct.c -DPORTABLE
$ ./struct 
sizeof(s.data) = 11
sizeof(s.intv) = 4
sizeof(s) =      16
$ gcc -o struct struct.c 
$ ./struct 
sizeof(s.data) = 11
sizeof(s.intv) = 4
sizeof(s) =      15

Откуда взялся дополнительный байт?

Я всегда думал, что 11 + 4 = 15, а не 16.

Ответы [ 3 ]

4 голосов
/ 28 декабря 2011

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

.быть полезным в сохранении элементов и самих структур выровненными по определенным границам, чтобы избежать ошибок выравнивания (возможно, почему это включено с -DPORTABLE) и как оптимизация скорости, как указывает Алс.

2 голосов
/ 28 декабря 2011

Это связано с заполнением структуры .
Компиляторы могут добавлять дополнительные байты заполнения к структурам для оптимизации времени доступа.

По этой причине Вы всегда должны использовать оператор sizeof и никогда не вычислять размер структур вручную.

1 голос
/ 28 декабря 2011

Это называется выравниванием. Это особенно добавило заполнение в конце структур, чтобы уменьшить потери в кеше. Если вы хотите отключить его, вы можете использовать что-то вроде этого:

#pragma pack(push)  /* push current alignment to stack */
#pragma pack(1)     /* set alignment to 1 byte boundary */

typedef struct {
  unsigned char data[11];

#ifdef PORTABLE
  unsigned long intv;
#else
  unsigned char intv[4];
#endif
} struct1;

#pragma pack(pop)   /* restore original alignment from stack */
...