2011-12-28 32 views
0

当我使用-DPORTABLE进行编译时,这段代码有什么问题?gcc 4.3.4结构大小错误?

#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.

回答

4

没有什么错的代码;这些尺寸是正确的。编译器可以酌情添加填充到structstruct的尺寸只能保证足够大以容纳其元素,因此添加其元素的尺寸并不是获得struct尺寸的可靠方法。

这样的填充有助于保持元素和结构本身与特定的边界对齐,以避免对齐错误(可能为什么它启用-DPORTABLE)并作为速度优化,正如Als指出的那样。

2

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

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

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 */ 
+0

感谢您的代码! – einclude 2011-12-28 16:20:59