Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does the size of a struct change depending on whether an initial value is used?

In the following code, both D1 & D2 have the same data members. However, the object size is different depending on whether the last member of the base class is initialized.

#include <cstdint>

struct B1 { int x; short y = 0; };
struct D1 : B1 { short z; };
struct B2 { int x; short y; };
struct D2 : B2 { short z; };
static_assert(sizeof(D1) == sizeof(D2));

GCC 14.2 (and Clang 18.0.1) fails with:

<source>:7:26: error: static assertion failed
    7 | static_assert(sizeof(D1) == sizeof(D2));
      |               ~~~~~~~~~~~^~~~~~~~~~~~~
<source>:7:26: note: the comparison reduces to '(8 == 12)'

What is the explanation for this behavior?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

This is an arbitrary ABI choice for compatibility with C.

In the Itanium C++ ABI, used by GCC and Clang here, B2 is considered POD for the purpose of layout while B1 is not. (It is reasonable because B2 is a valid C type as well, while B1 is not.)

The ABI specifies that tail padding of a type will be reused only if it is not POD for the purpose of layout. (So e.g. memcpy/memset as typically used in C is safe on the base class subobject if the base class type is POD for the purpose of layout and won’t overwrite any derived class members. And in C the compiler is always allowed to overwrite padding if a member is modified, so even without calls to memcpy, etc. using the base class subobject in C would otherwise not be compatible with C++.)

Both B1 and B2 have two bytes tail padding. D1 will reuse it to fit the z member, while D2 will not and leave the two padding bytes empty instead. Because the size of the whole class must be a multiple of its alignment which is 4 because of the int member, D2 then also needs to add two additional new tail padding bytes.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading