结构对齐可能会浪费内存?

Posted

技术标签:

【中文标题】结构对齐可能会浪费内存?【英文标题】:Struct alignment may waste memory? 【发布时间】:2020-02-11 04:34:25 【问题描述】:

现在我有一个 struct st,其中包含另一个 struct:

struct st2 
    char b = 2;
    long c = 3;
;

struct st 
    char a = 1;
    st2 mySt;
    int d = 4;
    char e = 5;
;

当我在内存中检查这个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

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

那么问题来了:为什么编译器没有与每个子结构中的基本类型对齐,而是与整个子结构的大小对齐?这不是浪费内存吗?

【问题讨论】:

【参考方案1】:

st2 的所有实例都具有相同的布局。存储对象的位置可能不会影响该布局。对象是否是成员可能不会影响该布局。编译器不能简单地选择mySt 的成员之一并将其存储在对象之外。

考虑将st2 传递给函数:

void some_function(st2&);

该函数无法知道该对象来自何处。但它必须能够访问对象的成员。对象的布局必须在编译时知道。如果st2 的一个实例与另一个实例的布局不同,该函数如何知道?

【讨论】:

以上是关于结构对齐可能会浪费内存?的主要内容,如果未能解决你的问题,请参考以下文章

结构体中的数据对齐

C语言 | 关于结构体内存对齐,看这篇就够了

结构体内存对齐

内存管理简便复习总结

C++ 结构体对齐

结构体对齐——结构体内存布局