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:
intis 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
bshould be allocated aftera, and thatcshould be allocated afterb.On a platform where
intis 4 bytes wide, and requires 4-byte alignment, this leaves 12 bytes as the smallest valid size:atakes the first 4 bytesbtakes one bytecneeds 4 bytes, but must be allocated on a 4-byte boundary.bended one byte past such a boundary, so the next valid position to placecat 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, binstead.The containing class (
A) inherits the alignment requirement from the strictest-aligned member object. That is, because it contains anint, it has the same alignment requirement as anintdoes. And because the object’s total size must be a multiple of its alignment requirement, a class containing the members in the ordera, b, cwould still require 12 bytes of storage. It’d just shift the 3 bytes of padding to the end of the class, instead of betweenbandc.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:
This would have required 24 bytes of storage (1 bytes for
a, 8 byte forb, and 4 bytes forc, but then to ensurebends up on an 8-byte boundary, we’d need 7 bytes of padding betweenaandb, and to ensure that the whole class ends up with a size that is a multiple of 8, we need another 4 bytes afterc.But reordering the members according to size, like this:
results in a class requiring only 16 bytes:
the same 1 + 4 + 8 bytes for the member objects themselves, but now
cis already aligned on a 4-byte boundary (because it comes afterbwhich ends on an 8-byte boundary), andanever needs any alignment, so the only alignment we need is to ensure thatBhas 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.