我正在编写解压缩PE文件的程序。我有一个结构,Pe_SymbolHeader。它看起来像这样:
typedef struct _Pe_SymbolHeader {
char Name[8]; // 8
uint32_t Value; // 12
uint16_t SectionNumber; // 14
uint16_t Type; // 16
uint8_t StorageClass; // 17
uint8_t NumberOfAuxSymbols; // 18
} Pe_SymbolHeader;
gcc告诉我这个结构的大小是20个字节。
printf("sizeof Pe_SymbolHeader %d\n", sizeof(Pe_SymbolHeader));
我决定在堆栈上放置一个Pe_SymbolHeader并查看内存中所有内容的位置
Pe_SymbolHeader test
printf("%p\n", &(test.Name));
printf("%p\n", &(test.Value));
printf("%p\n", &(test.SectionNumber));
printf("%p\n", &(test.Type));
printf("%p\n", &(test.StorageClass));
printf("%p\n", &(test.NumberOfAuxSymbols));
这给了我以下内容,似乎没问题:
0x7fffffffe150
0x7fffffffe158
0x7fffffffe15c
0x7fffffffe15e
0x7fffffffe160
0x7fffffffe161
因此,如果gcc使用18个字节来存储我的结构,为什么sizeof告诉我结构将占用20个字节?
编辑:好的,似乎gcc正在尝试帮助我的是杀死我的东西,并且有几个答案是正确的。我只能投一票,但谢谢那些回答的人。
答案 0 :(得分:3)
结构的uint32_t
部分需要在4个字节的倍数上对齐,因此结构的大小必须是4个字节的倍数,以确保结构的数组不会引起麻烦(未对齐的访问问题 - 这可能导致某些机器上的SIGBUS错误以及(大多数)其他机器上的(非常)低效访问)。因此,编译器要求在结构的末尾添加2个填充字节;这些没有名字,所以你不能合法地访问它们。
答案 1 :(得分:3)
结构的末尾有填充。
原因与数组中发生的事情有关,或者某些其他上下文跟你的结构有关。那个东西可能是这个结构的另一个实例。该结构包含一个32位对象,因此它的对齐要求为32位。
编译器非常希望下一个项目在它正在编译的体系结构的自然字边界上开始,这样下一个对象中的任何字段都可以通过一个操作而不是两个操作来读取,另外还有一些可以组合起来两个不同的“单词”。
答案 2 :(得分:2)
因此,如果gcc使用18个字节来存储我的结构,为什么sizeof告诉我结构将占用20个字节?
将2个这样的结构放在堆栈上并为它们打印相同的东西,这将启发你。
答案 3 :(得分:1)
uint32_t Value;
这增加了6个字节而不是预期的4.我倾向于同意Jonathan Leffler的基本原因。