继承和属性打包

skg*_*nga 5 c++ g++ clang++

考虑一下C ++中的这段代码

struct Base
{
   std::int64_t x;
   std::int64_t y;
};
static_assert(sizeof(Base) == 16, "Base not of size 16!");

struct Derived : Base
{
   std::int32_t z;
}__attribute__((packed));
static_assert(sizeof(Derived) == 20, "Derived not of size 20!");
Run Code Online (Sandbox Code Playgroud)

clang认为此代码有效,因为gcc会导致第二个static_assert触发。(“不是大小为20的派生!)。如果我还添加了打包在Base中的属性,则在两个编译器中都可以。没有人知道哪个是正确的,为什么?

Jes*_*uhl 5

两者都是对的。

允许编译器向您的类添加填充(在成员之间和最后)并且它是实现定义的,无论是否添加,因此您的static_assert's 基本上是在测试依赖于所使用的编译器(和平台)的东西 - 因此它们不可移植,您不能期望在任何地方都能获得相同的结果。

您对 的使用__attribute__((packed))基本上告诉了解该属性的编译器,您想要特定的行为而不是默认情况下会做什么。在这种情况下,这可能会生成您想要的结果,但它也有影响(内存布局/使用和某些 CPU 性能)。而且您仍然不能确定所有编译器都会这样做。