Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my union's size bigger than I expected?

Tags:

c++

unions

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]

like image 705
Saurabh Ghorpade Avatar asked Aug 27 '11 04:08

Saurabh Ghorpade


People also ask

How is size of union calculated?

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).

Why is the size of a struct greater than union?

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.

What is the size of an union?

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.


2 Answers

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.

like image 89
hmakholm left over Monica Avatar answered Oct 17 '22 13:10

hmakholm left over Monica


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.

like image 43
Nicol Bolas Avatar answered Oct 17 '22 15:10

Nicol Bolas