现在我有一个 struct st,其中包含另一个结构:
struct st2 {
char b = 2;
long c = 3;
};
struct st {
char a = 1;
st2 mySt;
int d = 4;
char e = 5;
};
Run Code Online (Sandbox Code Playgroud)
当我在内存中检查这个 struct st 时,它是这样的:
0x7fffffffdce0: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffffffdce8: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffffffdcf0: 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffffffdcf8: 0x04 0x00 0x00 0x00 0x05 0x00 0x00 0x00
Run Code Online (Sandbox Code Playgroud)
似乎 mySt 的第一个字符按 8 对齐(在 x64 中,我认为这是使用 struct st2 的大小,并且 #pragma pack 默认为 8)。
但是,如果你让我设计编译器,我会把mySt拆开,把mySt的每个基本类型都当作st的,所以成员a和b之间应该没有填充:
struct st {
char a = 1;
char b = 2; // unwind mySt
long c = 3; // unwind mySt
int d = 4;
char e = 5;
};
// Now the char a and b can storage in just one qword, by unwinding the sub structure.
0x7fffffffdcf0: 0x01 0x02 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffffffdcf8: 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffffffdd00: 0x04 0x00 0x00 0x00 0x05 0x00 0x00 0x00
Run Code Online (Sandbox Code Playgroud)
那么问题来了:为什么编译器不与每个子结构中的基本类型对齐,而是与整个子结构的大小对齐?那不是浪费内存吗?
的所有实例都st2具有相同的布局。存储对象的位置可能不会影响该布局。对象是否为成员可能不会影响该布局。编译器不能简单地选择 的成员之一mySt并将其存储在对象之外。
考虑传入st2一个函数:
void some_function(st2&);
Run Code Online (Sandbox Code Playgroud)
该函数无法知道该对象来自何处。但它必须能够访问对象的成员。必须在编译时知道对象的布局。如果 的一个实例与另一个实例st2具有不同的布局,该函数如何知道?