C++对象填充的复杂

C++对象填充的复杂,c++,class,memory,padding,C++,Class,Memory,Padding,我试图深入理解结构和类填充,所以我设计了一个比我在有关该主题的教程中找到的许多示例更具挑战性的示例。我用g++在x64机器上编译了它,没有启用任何代码优化。我的代码如下: class Example { private: long double foobar; // 10 bytes + 6 padded bytes as double follows double barfoo; // 8 bytes + 8 padded by

我试图深入理解结构和类填充,所以我设计了一个比我在有关该主题的教程中找到的许多示例更具挑战性的示例。我用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;
}
虽然我看到示例的大小是48字节,但我希望它是37字节。关于我的期望的论证如下:

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;
}
foobar需要10个字节。如下所示,填充还需要6个字节。 barfoo需要8个字节,因为它是一个双字节。不需要填充,因为mod16,8==0 *fooputs需要8个字节,因为它是x64体系结构中的指针。不需要填充,因为mod24,8==0 footsa需要4个字节作为int。不需要填充,因为mod32,4==0 foo需要1个字节作为字符。不需要填充。

由于结果与预期不同,我试图理解C++如何通过注释类成员来评估示例的大小到48字节。所以,除了对foobar的论证之外,我还假设了我在我的内联评论中为每个成员写的理由

谁能解释一下大小是如何计算为48字节的,以及我的理由是否正确吗?

你忘了最后的填充。sizeof返回一个值。在您的例子中,alignoflong double很可能是16,因此每个示例实例都需要位于16字节对齐的地址


因此,如果示例的第一个实例位于16字节对齐的地址a,而成员需要37字节,则下一个示例实例不能存储在+37字节处,但需要存储在+k*16处。满足k*16>=37的最小可能k为3。这最后给出了数组3*16=48中两个示例实例之间的字节数,这正是sizeofExample。

请参见此,了解为什么37的大小是不好的:您在代码中的注释建议的总和是45,而不是37。@DanielLangr您能详细说明sizeof完成的最终填充吗?我计算了48个字节。你的评论是正确的。长双精度+双精度+浮点*=16+16+16=48。我忽略了所有有填充空间的变量。x64上的长双8字节不是吗?80位格式适用于32位模式下的x87;x64使用SSE2。