请考虑以下示例:
#include <stdio.h>
#include <inttypes.h>
struct A {
uint32_t i1;
uint32_t i2;
uint32_t i3;
uint64_t i4;
uint32_t i5;
uint32_t i6;
uint32_t i7;
uint64_t i8;
uint32_t i9;
};
struct B {
uint32_t i1;
uint32_t i2;
uint32_t i3;
uint32_t i4;
uint32_t i5;
uint32_t i6;
uint32_t i7;
uint64_t i8;
uint64_t i9;
};
int
main()
{
struct A a;
struct B b;
printf("sizeof(a) = %u, sizeof(b) = %u\n", sizeof(a), sizeof(b));
return 0;
}
输出是:
$ ./t2
sizeof(a) = 56, sizeof(b) = 48
$
为什么它们在64位机器上有所不同?在32位平台上的结果是相同的:
$ ./t2
sizeof(a) = 44, sizeof(b) = 44
答案 0 :(得分:22)
一些图表可以帮助您查看:
32位:
+----+----+----+----+----+----+----+----+----+----+----+
| i1 | i2 | i3 | i4 | i5 | i6 | i7 | i8 | i9 | Struct A
+----+----+----+----+----+----+----+----+----+----+----+
+----+----+----+----+----+----+----+----+----+----+----+
| i1 | i2 | i3 | i4 | i5 | i6 | i7 | i8 | i9 | Struct B
+----+----+----+----+----+----+----+----+----+----+----+
64位:
+---------+---------+---------+---------+---------+---------+---------+
| i1 | i2 | i3 |~~~~| i4 | i5 | i6 | i7 |~~~~| i8 | i9 |~~~~| Struct A
+---------+---------+---------+---------+---------+---------+---------+
+---------+---------+---------+---------+---------+---------+
| i1 | i2 | i3 | i4 | i5 | i6 | i7 |~~~~| i8 | i9 | Struct B
+---------+---------+---------+---------+---------+---------+
答案 1 :(得分:8)
编译器通过边界(在编译尝试中不同)对齐struct成员。
添加
#pragma pack (1)
指令在源文件的开头并重试。
答案 2 :(得分:3)
因为它可以。编译器不需要在32位和64位模式之间使用相同的布局。它可以在需要时插入填充。您不应该首先依赖结构的精确布局。
原则上,它甚至可以在每次编译时更改填充。 (很难想象为什么编译器会这样做,但它被允许)
答案 3 :(得分:2)
64位整数必须放在64位内存边界上。因此,当在64位机器上创建结构A时,编译器在i3和i7之后粘贴一个4字节的填充空间 - 从而在那里增加了8个字节。
答案 4 :(得分:1)
由于元素之间的填充。
答案 5 :(得分:1)
这是由于结构对齐引起的:struct A
有3个32位值,后跟64位值。无论前3个元素的打包如何,64位元素肯定不会在64位之间的边界之间开始(即占据两个独立的64位值的一半),因此在第3和第4个元素之间至少有32位填充。
答案 6 :(得分:0)
答案 7 :(得分:0)
这是因为对齐。
平台上的64位整数可能需要64位对齐。
所以在混合结构中你有3个32位整数,在它们之后必须插入另一个32位填充以使64位整数正确对齐。
如果在64位字段之前插入偶数32位字段,则大小差异应该消失。