Do class/struct members always get created in memory in the order they were declared?
这是罗布·沃克的回答引发的一个问题。
假设我这样声明一个类/结构:
1 2 3 4 5 6 7 | struct { char A; int B; char C; int D; }; |
假设这些成员在内存中的声明顺序正好是这样的,或者这是一个依赖于编译器的东西,这样做安全吗?我问是因为我一直认为编译器可以用它们做任何它想做的事情。
这引出了我的下一个问题。如果上面的示例导致内存对齐问题,为什么编译器不能将其隐式地转换为类似这样的内容:
1 2 3 4 5 6 7 | struct { char A; char C; int B; int D; }; |
(我主要是问C++,但我也很想听到C的答案)
相关主题- 为什么GCC不优化结构?
C99§6.7.2.1第13条规定:
Within a structure object, the
non-bit-?eld members and the units in
which bit-?elds reside have addresses
that increase in the order in which
they are declared.
然后再多说一些填充和地址。C89等效章节为§6.5.2.1。
C++有点复杂。在1998和2003标准中,有第9.2条第12条(第15条中的C++ 11):
Nonstatic data members of a
(non-union) class declared without an
intervening access-specifier are
allocated so that later members have
higher addresses within a class
object. The order of allocation of
nonstatic data members separated by an
access-specifier is unspecified
(11.1). Implementation alignment
requirements might cause two adjacent
members not to be allocated
immediately after each other; so might
requirements for space for managing
virtual functions (10.3) and virtual
base classes (10.1).
数据成员按声明的顺序排列。编译器可以随意散布填充来排列它喜欢的内存对齐方式(并且您会发现许多编译器都有一个booatload对齐规范选项——如果混合了由不同程序编译的位,这很有用)。
另请参见gcc为什么不优化结构?.
看来C++的答案有些过时了。你每天都会学到一些东西。谢谢你,内曼扎。
基本上,您只能依赖于具有标准布局的类。严格来说,标准布局是一个C++ 0x的东西,但它实际上只是在规范现有的实践。
除了填充的对齐方式,没有任何结构优化允许任何编译器(我知道)的C或C++。我不能为C++类说话,因为它们可能完全是另一种野兽。
考虑您的程序正在与Windows上的系统/库代码接口,但您希望使用gcc。您必须验证gcc使用了相同的布局优化算法,以便在将所有结构发送到MS编译的代码之前正确打包它们。
我不能为C++说话,但是在C中,顺序保证在结构中声明的内存中的顺序相同。
当浏览右侧的相关主题时,我看到了这个问题。我认为在考虑这些问题时,这可能是一个有趣的角落案例(除非它比我意识到的更常见)。
要解释,如果您有一个C中的结构看起来像这样:
1 | struct foo{}; |
和它在C ++中使用的子类(使用单独的编译单元):
1 2 | extern"C" foo; struct bar: public foo{}; |
那么,由于AIB提到的原因(即使是同一供应商的编译器之间),内存对齐也不一定是相同的。