The following is an excerpt from a code sample in K&R's The C Programming Language (section 8.7):
typedef long Align;
union header {
struct {
union header *ptr;
unsigned size;
} s;
Align x;
};
typedef union header Header;
And here is the explanatory excerpt:
To simplify alignment, all blocks are multiples of the header size, and the header is aligned properly. This is achieved by a union that contains the desired header structure and an instance of the most restrictive type, which we have arbitrarily made a long.
So, as I understand it, the idea is to ensure that a header instance takes up a number of bytes that is a multiple of sizeof(Align). The goal makes perfect sense to me.
But consider the case where long is 64 bits, int is 32 bits, and a pointer is 64 bits. In that case, header.s will be 64+32 = 96 bits. Thus, sizeof(header) will be 96 bits, which is not a multiple of 64 as intended.
In such a case, I suppose it would be necessary to define Align as something else (perhaps double). But I'm not quite sure whether I'm fully understanding what would dictate that choice for a particular architecture. Is it just the "biggest" type? And what if long is the biggest type - couldn't it fail to work in the way I described above?
Thanks
The compiler will adjust the size of header so that ptr, size, and x can all be retrieved efficiently from elements in a header[] array. On most architectures, the presence of x means that sizeof(header) will be increased to a multiple of sizeof(long).
The size of a union is at least as large as the size of its largest member. So, even if sizeof(s) is 12 and sizeof(long) is 8, as in your example, you will still have sizeof(header) >= 12. Likewise, the alignment of a union is largest alignment of any of its members, so the presence of the long member ensures that the alignment of header is at least the alignment of long, which would be 8 in this case.
If you compile this code, you will almost certainly find that sizeof(header) is 16, not 12. The reason is that if you have an array of header objects, the compiler needs to ensure that the alignment of any of the members is proper, and arrays are stored contiguously in memory. In order to achieve that, the size needs to be a multiple of the alignment. The compiler does that by adding an extra 4 bytes of padding to the end of a header object.
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