使用-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。
答案 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 */