gcc 4.3.4结构大小的bug?

时间:2011-12-28 15:49:40

标签: gcc struct

使用-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 个答案:

答案 0 :(得分:4)

代码没有错;那些尺寸是正确的。编译器可以自行决定向struct添加填充。 struct的大小只能保证足够大以容纳其元素,因此添加元素的大小并不是获得struct大小的可靠方法。

这样的填充有助于保持元素和结构本身与特定边界对齐,既可以避免对齐错误(也许是为什么它可以通过-DPORTABLE启用),也可以像Als所指出的那样进行速度优化。

答案 1 :(得分:2)

这是由于 structure padding 编译器可以自由地向结构添加额外的填充字节以优化访问时间。

这就是您应该始终使用 sizeof 运算符并且从不手动计算结构大小的原因。

答案 2 :(得分:1)

这叫做对齐。这特别是在结构末端添加填充以减少缓存未命中。如果你想禁用它,你可以使用类似的东西:

#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 */