47

这是Rob Walker在此处的回答引发的一个问题。

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

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

假设这些成员将在内存中完全按照该顺序声明是否安全,或者这是依赖于编译器的事情?我问是因为我一直认为编译器可以对它们做任何想做的事情。

这就引出了我的下一个问题。如果上面的例子导致内存对齐问题,为什么编译器不能隐式地把它变成这样的东西:

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

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

相关话题

4

6 回答 6

80

C99 §6.7.2.1 第 13 条规定:

在结构对象中,非位域成员和位域所在的单元的地址按声明顺序递增。

并继续说更多关于填充和地址的内容。C89 等效部分是 §6.5.2.1。

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

分配没有中间访问说明符的(非联合)类的非静态数据成员,以便后面的成员在类对象中具有更高的地址。由访问说明符分隔的非静态数据成员的分配顺序未指定 (11.1)。实现对齐要求可能会导致两个相邻的成员不会被立即分配;管理虚拟功能 (10.3) 和虚拟基类 (10.1) 的空间要求也是如此。

于 2008-11-11T14:50:01.970 回答
4

数据成员按声明的顺序排列。编译器可以随意散布填充以安排它喜欢的内存对齐方式(您会发现许多编译器都有一个对齐规范选项——如果混合不同程序编译的位时很有用。)。

另请参阅为什么 GCC 不优化结构?.


看来这个答案对于 C++ 来说有些过时了。你每天都会学到一些东西。谢谢 aib,内曼加。

于 2008-11-11T14:46:16.970 回答
3

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

于 2008-11-11T14:46:14.910 回答
3

基本上,您只能指望具有标准布局的类。严格来说,标准布局是 C++0x 的东西,但实际上只是标准化现有的做法/

于 2008-11-11T14:47:09.370 回答
2

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

考虑您的程序正在与 Windows 上的系统/库代码交互,但您想使用 GCC。您必须验证 GCC 是否使用了相同的布局优化算法,以便在将所有结构发送到 MS 编译代码之前正确打包它们。

于 2008-11-11T14:51:30.220 回答
0

在浏览右侧的相关主题时,我查看了这个问题。在考虑这些问题时,我认为这可能是一个有趣的极端案例(除非它比我意识到的更常见)。

解释一下,如果你在 C 中有一个看起来像这样的结构:

struct foo{};

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

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

由于aib提到的原因,内存对齐不一定相同(即使在来自同一供应商的编译器中)。

于 2008-11-11T15:10:45.670 回答