struct K is packed and the sum of it's class member sizes is 36. Each member has a static_assert checking this.
However, the size of K itself is 40, not 36. K isn't polymorphic etc.
Why is K not size 36?
Using Clang 16. I'm not aware of an easy way to visualize the struct, or I would have. If anyone can recommend a way that would be great.
template<class S>
struct P
{};
struct D : public P<D>
{
uint64_t x_;
};
enum class E : uint8_t
{};
struct K
{
D a_;
D b_;
uint64_t c_;
uint64_t d_;
uint16_t e_;
E f_;
E g_;
static_assert(sizeof(a_) == 8); // Passes
static_assert(sizeof(b_) == 8); // Passes
static_assert(sizeof(c_) == 8); // Passes
static_assert(sizeof(d_) == 8); // Passes
static_assert(sizeof(e_) == 2); // Passes
static_assert(sizeof(f_) == 1); // Passes
static_assert(sizeof(g_) == 1); // Passes
}__attribute__((packed));
static_assert(sizeof(K) == 36); // Fails, is 40 instead of 36
int main()
{
K f;
}
With warnings enabled for clang, the issue becomes obvious:
Neither GCC nor clang seem to document this behavior (see GCC
packedattribute, clangpackedattribute), but it looks like using inheritance (fromP<D>) disables the effect ofpackedfor a member. There is no inherent reason whyDcouldn't be packed in this case, it simply appears to be a general ban.If any member isn't packed, to ensure proper alignment of all members, the
structrequires additional padding. The alignment ofKis8, as evidenced by:Since
Kis aligned to 8 bytes, and the combined size of its members is 36, 4 padding bytes have to be added at the end to correctly alignKto 8 bytes (by increasing its size to 40).See Also