class / struct成员是否总是按照声明的顺序在内存中创build?

这是Rob Walker 在这里的答案引发的一个问题。

假设我像这样声明了一个类/结构体:

struct { char A; int B; char C; int D; }; 

假设这些成员在内存中将按照正确的顺序进行声明是安全的,还是依赖于编译器呢? 我问,因为我一直认为编译器可以做任何想做的事情。

这导致我的下一个问题。 如果上面的例子导致内存alignment的问题,为什么编译器不能把它变成这样的隐式:

 struct { char A; char C; int B; int D; }; 

(我主要是问C ++,但我也有兴趣听到C的答案)

相关话题

  • 为什么GCC不优化结构?

C99§6.7.2.1第13条规定:

在一个结构对象中,非位字段成员和位字段所在的单元的地址增加了它们的声明顺序。

并继续说更多关于填充和地址。 C89相当的部分是§6.5.2.1。

C ++有点复杂。 在1998和2003标准中,有§9.2第12条(C ++ 11第15条):

非声明的(非联合)类的非静态数据成员被声明为没有插入的访问说明符,以便后来的成员在类对象中拥有更高的地址。 未指定由访问说明符分隔的非静态数据成员的分配顺序(11.1)。 执行alignment要求可能会导致两个相邻的成员不能立即分配; 所以可能需要pipe理虚拟function(10.3)和虚拟基类(10.1)的空间。

数据成员按声明顺序排列。 编译器可以自由填充填充来安排它喜欢的内存alignment(你会发现许多编译器有一个alignment的规格选项 – 如果混合不同的程序编译位有用)。

另请参见为什么不GCC优化结构? 。


看来,这个答案已经过时了C ++。 你每天都能学到东西。 谢谢你,Nemanja。

基本上,只有具有标准布局的类才可以依靠它。 严格来说,标准布局是一个C ++ 0x的东西,但它只是标准化现有的做法/

我不能说C ++,但在C中的顺序是保证是在内存中的结构中声明的相同的顺序。

除了用于alignment的填充之外,对于C或C ++,任何编译器(我都知道)不允许进行结构优化。 我不能说C ++类,因为它们可能完全是另一个野兽。

考虑一下你的程序是与Windows系统/库代码接口,但是你想使用GCC。 您将不得不validationGCC使用了相同的布局优化algorithm,以便在将所有结构发送到MS编译代码之前将其正确打包。

在浏览右侧的相关主题的同时,我看了一下这个问题 。 我想这可能是一个有趣的angular落案例时,思考这些问题(除非它比我所知道的更普遍)。

换句话说,如果你有一个C中的结构,看起来像这样:

 struct foo{}; 

并在C ++中使用它的子类(使用单独的编译单元):

 extern "C" foo; struct bar: public foo{}; 

然后,由于aib提到的原因(甚至在同一个厂商的编译器之间),内存alignment不一定是相同的。