这是Rob Walker的答案here引发的问题。
假设我像这样声明一个类/结构:
struct
{
char A;
int B;
char C;
int D;
};
是否可以安全地假设这些成员将在内存中以完全相同的顺序声明,或者这是否依赖于编译器?我问,因为我一直认为编译器可以随心所欲地做任何事情。
这引出了我的下一个问题。如果上面的例子导致内存对齐问题,为什么编译器不能只是隐式地将它变成这样的东西:
struct
{
char A;
char C;
int B;
int D;
};
(我主要是询问C ++,但我也有兴趣听到C答案)
答案 0 :(得分:72)
C99§6.7.2.1第13条规定:
在结构对象中, 非比特场成员和中的单位 哪些位域具有地址 按顺序增加 他们被宣布。
继续谈论填充和地址。 C89等效部分是§6.5.2.1。
C ++有点复杂。在1998年和2003年的标准中,有第9.2条第12款(C ++ 11第15条):
a的非静态数据成员 (非联合)类声明没有 干预访问说明符 分配,以便以后的成员 一个班级中较高的地址 宾语。分配顺序 由...分隔的非静态数据成员 access-specifier未指定 (11.1)。实施一致 要求可能导致两个相邻 成员不得分配 紧接着彼此;可能 管理空间要求 虚函数(10.3)和虚函数 基类(10.1)。
答案 1 :(得分:4)
数据成员按声明的顺序排列。编译器可以自由地散布填充以安排它喜欢的内存对齐(并且你会发现很多编译器都有一个对齐规范选项 - 如果混合由不同程序编译的位,则很有用。)。
另见Why doesn't GCC optimize structs?。
对于C ++来说,这个答案似乎有点过时了。你每天都学到东西。谢谢aib,Nemanja。
答案 2 :(得分:3)
基本上,只有具有standard layout的班级才能指望这一点。严格地说,标准布局是C ++ 0x的事情,但它实际上只是标准化现有的实践/
答案 3 :(得分:2)
我不能代表C ++,但在C中,顺序保证与结构中声明的内存顺序相同。
答案 4 :(得分:2)
除了用于对齐的填充之外,C或C ++的任何编译器(我都知道)不允许进行结构优化。我不能代表C ++课程,因为它们可能完全是另一个野兽。
考虑您的程序是否与Windows上的系统/库代码连接,但您想使用GCC。您必须验证GCC使用相同的布局优化算法,以便在将它们发送到MS编译的代码之前正确打包所有结构。
答案 5 :(得分:0)
在浏览右侧的相关主题时,我查看了this question。我认为在考虑这些问题时这可能是一个有趣的角落(除非它比我意识到的更常见)。
换句话说,如果C中的结构看起来像这样:
struct foo{};
并在C ++中使用它(如使用单独的编译单元)将其子类化:
extern "C" foo;
struct bar: public foo{};
然后,由于aib提到的原因(即使是来自同一供应商的编译器),内存对齐也不一定相同。