When I print the size of a union like this:
union u {
char c[5];
int i;
} un;
using this:
int _tmain(int argc, _TCHAR* argv[])
{
printf("size of union = %d ",sizeof(un));
return 0;
}
I get an answer of 8 using Visual C++, but I expected 5. Why?
Well, for the same example, i did something like this:
int i1 = 0x98761234;
un.i = i1;
printf("\n un.c[0] = %x ",un.c[0]);
printf("\n un.c[1] = %x ",un.c[1]);
printf("\n un.c[2]= %x ",un.c[2]);
printf("\n un.c[3] = %x ",un.c[3]);
printf("\n un.c[4] = %x ",un.c[4]);
printf("size of union = %d ",sizeof(un));
i got results like
un.c[0] = 34;
un.c[1] = 12;
un.c[2] = 76;
un.c[3] = ffffff98;
why are there 6fs at un.c[3]
When we declare a union, memory allocated for the union is equal to memory needed for the largest member of it, and all members share this same memory space. Since u is a union, memory allocated to u will be max of float y(4 bytes) and long z(8 bytes). So, total size will be 18 bytes (10 + 8).
The size of a structure is the sum of the size of all data members and the packing size. The size of the union is the size of its data member, which is the largest in size.
The size of the union is based on the size of the largest member of the union. Let's understand through an example. As we know, the size of int is 4 bytes, size of char is 1 byte, size of float is 4 bytes, and the size of double is 8 bytes.
The sizeof
operator produces the size of a variable or type, including any padding necessary to separate elements in an array of that type such that everything is still correctly aligned. Since your union has an int
member, it needs to be 4-byte aligned, so its "natural" size gets rounded upwards to the next multiple of 4 bytes.
The ffffff98
is because you're compiling with signed char
. Using %x
with an argument that is not unsigned int
causes undefined behaviour; what you're seeing is sometimes called sign-extension. The result of your aliasing is 0x98
reinterpreted as char
, which is -104
. This retains its value on being promoted to int
(this is called the default argument promotions), and the int -104
when aliased as unsigned int
becomes 0xffffff98
.
The alignment of your union must be the largest alignment of any of its members. This is 4. Therefore, the size of the union must be aligned to that size. It could have been 5 (as c
is the largest member of the union), but because the alignment of the union as a whole is 4, the size of the union is padded to 8.
Note that this is just for VC++. The standard does not specifically require it. Though it does allow implementations to pad types as needed, which VC++ does. GCC could do something different, and there could be compile-time switches you could employ to change this behavior.
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