【问题标题】:Do class/struct members always get created in memory in the order they were declared?类/结构成员是否总是按照声明的顺序在内存中创建?
【发布时间】:2010-09-21 19:35:37
【问题描述】:

这是Rob Walker 的回答here 引发的问题。

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

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

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

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

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

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

相关主题

【问题讨论】:

    标签: c++ memory memory-alignment


    【解决方案1】:

    C99 §6.7.2.1 第 13 条规定:

    在结构对象中, 非位域成员和单元 哪些位域驻留有地址 增加的顺序 它们被声明了。

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

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

    a 的非静态数据成员 (非联合)类声明没有 干预访问说明符是 分配给后来的成员 类中的更高地址 目的。分配顺序 非静态数据成员由 访问说明符未指定 (11.1)。实施对齐 要求可能会导致两个相邻 不被分配的成员 紧随其后;所以可能 管理空间要求 虚函数(10.3)和虚函数 基类 (10.1)。

    【讨论】:

    • 这个答案很到位。唯一需要注意的是,并非所有编译器都遵循标准。在确实遵循标准的编译器中,不一定在所有优化级别都遵循它。
    • /该死的/。我不知道那个访问说明符异常——幸运的是,我确信我没有任何代码依赖它。
    • C++11:现在是 §9.2 第 15 条:该段的措辞没有改变。
    • C 标准的“非位域成员”部分是否意味着允许编译器重新排序命名位域?
    • 我认为这意味着位域可能会被重新排序,但仅限于它们之间,即共享相同变量的那些。
    【解决方案2】:

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

    另见Why doesn't GCC optimize structs?


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

    【讨论】:

    • 感谢您的链接。我将其添加为相关主题。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

        • 真的吗?我总是被告知结构和类是完全一样的,除了结构默认为公共访问。或者这是整个“另一个问题”的主题?
        • C++ 类与 C++ 结构没有什么不同。 唯一的区别在于结构默认使用'public'作为成员或继承,而类使用'private。
        • @HUAGHAGUAH - 我希望你不介意,我稍微调整了你的帖子。我喜欢你的帖子,不希望任何人投反对票,因为关于 C++ 类的部分完全是另一种野兽。 :-)
        【解决方案6】:

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

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

        struct foo{};
        

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

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

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

        【讨论】:

          猜你喜欢
          • 2012-07-03
          • 2015-01-05
          • 2012-01-27
          • 1970-01-01
          • 2019-12-11
          • 1970-01-01
          • 2020-09-02
          • 2010-11-26
          • 1970-01-01
          相关资源
          最近更新 更多