Take this example
class A
{
public:
int a;
char b;
int c;
};
Every compiler (for x86, 32 or 64 bit) I see allocates 12 bytes for class A
, instead of 9. So they are aligning b
to the integer boundary or bus boundary you can say. My question is if this is in C++ standard to do so and if there are any compilers who does not do like that.
The C++ standard specifies that:
int
is 4 bytes wide, then it requires an alignment of 1, 2 or 4 bytes, depending on the implementation).public
) are all allocated in the order they're declaredSo no, the standard doesn't say exactly that the class should have a size of 12 bytes.
But it does say that b
should be allocated after a
, and that c
should be allocated after b
.
On a platform where int
is 4 bytes wide, and requires 4-byte alignment, this leaves 12 bytes as the smallest valid size:
a
takes the first 4 bytesb
takes one bytec
needs 4 bytes, but must be allocated on a 4-byte boundary. b
ended one byte past such a boundary, so the next valid position to place c
at is found by inserting 3 bytes of padding.So the total size of the class ends up being the size of the members (4 + 1 + 4 = 9) plus three bytes of padding, for a total of 12.
There is another rule which has no effect here, but which would matter if you had defined the members in the order a, c, b
instead.
The containing class (A
) inherits the alignment requirement from the strictest-aligned member object. That is, because it contains an int
, it has the same alignment requirement as an int
does. And because the object's total size must be a multiple of its alignment requirement, a class containing the members in the order a, b, c
would still require 12 bytes of storage. It'd just shift the 3 bytes of padding to the end of the class, instead of between b
and c
.
However, in some other cases, reordering members in descending order of size can sometimes reduce the size of a class.
Suppose we'd had a class like this instead:
class B {
char a;
double b;
int c;
};
This would have required 24 bytes of storage (1 bytes for a
, 8 byte for b
, and 4 bytes for c
, but then to ensure b
ends up on an 8-byte boundary, we'd need 7 bytes of padding between a
and b
, and to ensure that the whole class ends up with a size that is a multiple of 8, we need another 4 bytes after c
.
But reordering the members according to size, like this:
class B {
double b;
int c;
char a;
};
results in a class requiring only 16 bytes:
the same 1 + 4 + 8 bytes for the member objects themselves, but now c
is already aligned on a 4-byte boundary (because it comes after b
which ends on an 8-byte boundary), and a
never needs any alignment, so the only alignment we need is to ensure that B
has a size that is a multiple of 8. The members take 13 bytes, so we can add 3 bytes of padding, and the class ends up at 16 bytes, 33% smaller than the first version.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With