【问题标题】:C++ - object padding intricaciesC++ - 对象填充错综复杂
【发布时间】:2020-09-27 15:46:34
【问题描述】:

我试图深入了解结构和类填充,因此我设计了一个我认为比我在有关该主题的教程中找到的许多示例更具挑战性的示例。我用 g++ 在 x64 机器上编译它,没有启用任何代码优化。我的代码如下:

class Example
{
    private:
        long double foobar;     // 10 bytes + 6 padded bytes as double follows
        double barfoo;          // 8 bytes + 8 padded bytes
        static float barbar;    // didn't count as it's a static member
        float *fooputs;         // 8 bytes + 8 padded bytes
        int footsa;             // 4 bytes, stored in the padded portion of float
        char foo;               // 1 byte, stored in the padded portion of float

    public:
        int function1(int foo) { return 1; }
        void function2(int bar) { foobar = bar; }
};

int main()
{
    std::cout << sizeof(Example) << std::endl;   // 48 bytes
    return 0;
}

虽然我看到Example 的大小是 48 字节,但我希望它是 37 字节。我的期望的论证如下:

  • foobar 需要 10 个字节。正如double 之后的内容,还需要 6 个字节进行填充。
  • barfoo 需要 8 个字节,因为它是 double。不需要填充,如mod(16,8) == 0
  • *fooputs 需要 8 个字节,因为它是 x64 架构中的指针。不需要填充,如mod(24,8) == 0
  • footsa 需要 4 个字节作为 int。不需要填充,如mod(32,4) == 0
  • foo 需要 1 个字节作为字符。无需填充。

由于结果与预期不同,我试图通过注释 in 和 out 类成员来了解 C++ 如何将 Example 的大小评估为 48 字节。因此,除了foobar 的论证之外,我还假设了我在我的内联 cmets 中为每个成员编写的理由。

谁能解释一下如何将大小评估为 48 字节以及我的理由是否正确?

【问题讨论】:

  • 看看为什么 37 的大小会不好:stackoverflow.com/questions/58435348/…
  • 代码中的 cmets 建议的总和是 45,而不是 37。
  • @DanielLangr 你能详细说明 sizeof 完成的“最终填充”吗?
  • 我数了 48 个字节。你的cmets是正确的。 long double + double + float* = 16 + 16 + 16 = 48。(我忽略了所有有填充空间的变量。)
  • long double x64 上不是 8 字节吗? 80 位格式适用于 32 位模式下的 x87; x64 使用 SSE2。

标签: c++ class memory padding


【解决方案1】:

您忘记了最终填充sizeof 返回 number of bytes between two adjacent members in an array。在您的情况下,alignof(long double) 很可能是 16,因此每个 Example 实例都需要位于 16 字节对齐的地址。

因此,如果 Example 的第一个实例位于 16 字节对齐的地址 A,然后成员需要 37 个字节,则下一个 Example 实例无法存储在A + 37 字节,但需要存储在A + k * 16. 尽可能小的k满足 k * 16 >= 37 是 3。它最终为您提供了数组 3 * 16 = 48 中两个 Example 实例之间的字节数,这正是 sizeof(Example)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-05
    • 1970-01-01
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多