Suppose such structs: A
is out of our control but we can change the B
structure:
struct A {
int64_t x; // 8 bytes
int32_t y; // 4 bytes
// 4 padding bytes
};
struct B {
A a; // 16 bytes
int32_t z; // 4 bytes
// 4 padding bytes (alignof(B) == alignof(A) == 8)
};
static_assert(sizeof(B) == 24); // 8 useless bytes!
Is there a way to put z
inside A
padding (some attributes)?
Reuse of padding is determined by the ABI, not the standard or the compiler. For example, on Linux this will work:
struct A {
int64_t x; // 8 bytes
int32_t y; // 4 bytes
// 4 padding bytes
A() = default; // <-- CHANGE HERE
};
struct B {
[[no_unique_address]] A a; // <-- CHANGE HERE
int32_t z; // 4 bytes in the padding of A
};
static_assert(sizeof(B) == 16);
A
needs certain properties true of its type in order to be eligible for tail padding reuse. For this ABI, it needs to be not a POD as of C++03. Adding a user-declared constructor is sufficient.
Then within B
, we need to induce the use of tail padding. For example, if A
is a base class, it will reuse its tail padding. Alternatively, using [[no_unique_address]]
accomplishes the same.