为什么这个struct padding技巧有效?

PBS*_*PBS 28 c++ inheritance padding

考虑这个简单的程序

#include <iostream>

struct A
{
    int   x1234;
    short x56;
    char  x7;
};

struct B : A
{
    char x8;
};

int main()
{
    std::cout << sizeof(A) << ' ' << sizeof(B) << '\n';
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这打印8 12.即使B可以在不破坏对齐要求的情况下打包成8个字节,但它却占用了贪婪的12个字节.

这样会很好sizeof(B) == 8,但答案是结构的大小是否必须 是该结构对齐的精确倍数?表明没有办法.

因此,当以下时我感到惊讶

struct MakePackable
{
};

struct A : MakePackable
{
    int   x1234;
    short x56;
    char  x7;
};

struct B : A
{
    char x8;
};
Run Code Online (Sandbox Code Playgroud)

印刷8 8.

这里发生了什么?我怀疑标准布局类型与它有关.如果是这样,那么当该特性的唯一目的是确保与C的二进制兼容性时,它导致上述行为的理由是什么?


编辑:正如其他人已经指出这是ABI或编译器特定的,所以我应该补充说,这个行为是在x86_64-unknown-linux-gnu上使用以下编译器观察到的:

  • 铿锵3.6
  • gcc 5.1

我也注意到了clang的struct dumper中的一些奇怪的东西.如果我们要求没有尾部填充的数据大小("dsize"),

          A   B
first     8   9
second    7   8
Run Code Online (Sandbox Code Playgroud)

然后在我们得到的第一个例子中dsize(A) == 8.为什么这不是7?

The*_*ish 2

我不是真正的 C++ 语言律师,但到目前为止我发现的是:

参考这个问题的答案,结构体仅保留标准布局 POD,而其自身及其父类之间只有 1 个具有非静态成员的类。因此,在这种想法下,A在这两种情况下都有一个有保证的布局,但在这两种B情况下都没有。

支持这一点的是std::is_pod在两者中都为 trueA和 false的事实B

因此,如果我自己正确理解了这一点,那么在这两种情况下,编译器都可以有一些空间来完成它想要的布局B。显然,在第二种情况下,感觉像是利用了 的填充字节A