#include <stdio.h>
union u1 {
struct {
int *i;
} s1;
struct {
int i, j;
} s2;
};
union u2 {
struct {
int *i, j;
} s1;
struct {
int i, j;
} s2;
};
int main(void) {
printf(" size of int: %zu\n", sizeof(int));
printf("size of int pointer: %zu\n", sizeof(int *));
printf(" size of union u1: %zu\n", sizeof(union u1));
printf(" size of union u2: %zu\n", sizeof(union u2));
return 0;
}
Results in:
$ gcc -O -Wall -Wextra -pedantic -std=c99 -o test test.c
$ ./test
size of int: 4
size of int pointer: 8
size of union u1: 8
size of union u2: 16
Why does adding an integer of 4 bytes to nested struct s1 of union u2 increase the size of the union as a whole by 8 bytes?
The struct u2.s2
is 16 bytes because of alignment constraints. The compiler is guaranteeing that if you make an array of such structs, each pointer will be aligned on an 8-byte boundary. The field *i
takes 8 bytes, then j
takes 4 bytes, and the compiler inserts 4 bytes of padding. Because the struct is 16 bytes, the union containing it is also 16 bytes.
That's because the compiler needs to keep the entire struct (as well as the union) aligned to 8 bytes - due to the fact that you have a pointer inside. (which is 8-bytes in your case)
So even though you add only 4 bytes with the extra int
, struct-alignment forces everything to be aligned to 8 bytes - hence the +8 to bring the total size to 16 bytes.
The result of this is that:
struct {
int *i, j;
} s1;
has a size of 16 bytes. Since a union must be at least as large as the largest element, it is also forced up to 16.
http://en.wikipedia.org/wiki/Data_structure_alignment
Since a pointer is 8 bytes on your platform, it most probably also requires an alignment of 8 bytes. So when adding another 4 bytes, the struct cannot just have a size of 12 bytes, in which case the individual elements of say an array of u2
s would not be properly aligned at 8 byte boundaries, which is neccessary for the pointer member. So you need to increase its size to the next multiple of 8, which is 16. The additional 4 bytes are just unused/undefined.