Alex Lee
Alex Lee

Reputation: 171

Union usage and messy code

I have some code which is about the usage of union shown as following:

int main(){

  typedef union{int a;char b[10];float c;}Union;

  Union x,y = {100};
  printf("Union x :%d|   |%s|   |%f \n",x.a,x.b,x.c );
  printf("Union y :%d|   |%s|   |%f \n\n",y.a,y.b,y.c);

  x.a = 50;
  printf("Union x :%d|   |%s|   |%f \n",x.a,x.b,x.c );
  printf("Union y :%d|   |%s|   |%f \n\n",y.a,y.b,y.c);

  strcpy(x.b,"hello");
  printf("Union x :%d|   |%s|   |%f \n",x.a,x.b,x.c );
  printf("Union y :%d|   |%s|   |%f \n\n",y.a,y.b,y.c);

  x.c = 21.50;
  printf("Union x :%d|   |%s|   |%f \n",x.a,x.b,x.c );
  printf("Union y :%d|   |%s|   |%f \n\n",y.a,y.b,y.c);

  return 0;
}

After I compile and execute above code, I had result like this:

  Union x :0|     ||    |0.000000 
  Union y :100|   |d|   |0.000000 

  Union x :50|    |2|   |0.000000 
  Union y :100|   |d|   |0.000000 

  Union x :1819043176|     |hello|      |1143141483620823940762435584.000000 
  Union y :100|   |d|   |0.000000 

  Union x :1101791232|   ||    |21.500000 
  Union y :100|   |d|   |0.000000 

I do not know why the y.b is initialized as "d"? and why x.a and x.c's value changed after? why does the strcpy(x.b,"hello") not work?

Upvotes: 0

Views: 294

Answers (4)

Shafik Yaghmour
Shafik Yaghmour

Reputation: 158469

Strictly by the standard type-punning expect in narrow circumstances is undefined behavior but in practice many compilers support it for example gcc manual points here for type-punning and under -fstrict-aliasing section is says:

The practice of reading from a different union member than the one most recently written to (called “type-punning”) is common. Even with -fstrict-aliasing, type-punning is allowed, provided the memory is accessed through the union type.

I would recommend reading Understanding Strict Aliasing if you plan on using type-punning a lot.

y.b has the value b since all the elements of the union share memory and you initialized y with 100 which in ASCII is b. This is the same reason why the other fields of x change when you modify one including the case of strcpy and depending on your compiler this may be undefined or well defined(in the case of gcc it is defined).

For completeness sake the C++ draft standard section 9.5 Unions paragraph 1 says(emphasis mine):

In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time. [ Note: One special guarantee is made in order to simplify the use of unions: If a standard-layout union contains several standard-layout structs that share a common initial sequence (9.2), and if an object of this standard-layout union type contains one of the standard-layout structs, it is permitted to inspect the common initial sequence of any of standard-layout struct members; see 9.2. —end note ] The size of a union is sufficient to contain the largest of its non-static data members. Each non-static data member is allocated as if it were the sole member of a struct.

Upvotes: 3

alirakiyan
alirakiyan

Reputation: 428

I think when you say int a , you allocate sizeof(int) , generally 32 bits. but when you say char[10] , you are allocating 10 * sizeof(char) bytes !! (10 * 4 bits) these two can not be casted to each other.

Upvotes: -2

Your code has UB (undefined behaviour); it is illegal to assign to one member of a union and then inspect a different member (except for a special case of POD structs with the same initial members).

It is also illegal to read an uninitialised value, such as any field of x before you assign into x.a.

Upvotes: 2

Some programmer dude
Some programmer dude

Reputation: 409166

If you see an ASCII table you will see that the value 100 is the same as the character 'd'.

You have to remember that all members of a union shares the same memory. This means that if you set one member of a union, all members change, and not always to something comprehensible. Therefore it's undefined behavior to write to one member and read from another.

And strcpy(x.b,"hello") does indeed work, as you can see all the members of thex union change after you do that.

Upvotes: 2

Related Questions