Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is writing then reading different union members undefined according to the C standard? [duplicate]

I read that this code it is undefined according to the c standard but I cant find why. It is compiles without errors in gcc 8.1.0 and clang-6.0 and prints 1.

the code is as follows:

#include <stdio.h>

int main()
{
   union {
     int i;
     short s;
   } u;  
   u.i = 42;
   u.s = 1;

   printf("%d\n", u.i);
   return 0;
}
like image 517
theriver Avatar asked Dec 23 '22 03:12

theriver


2 Answers

From the C11 specification, §6.5.2.3 note 95:

If the member used to read the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type punning’’). This might be a trap representation.

This says that what you're doing is allowed, but also implies that the value you read may not be what you expect (for example by writing to an int member and reading from a float member).

There's also the caveat about trap representation values in which case the behavior will be undefined. For two's complement systems (which is the vast majority of all computers the last couple of decades) this isn't an issue with integer values though.


In your case the result will depends very much on the platforms endianness. Either you will get the value you write (1) or you will get 0.

like image 183
Some programmer dude Avatar answered Dec 31 '22 00:12

Some programmer dude


union {
    int i;
    short s;
  } u;  
u.i = 42;
u.s = 1;`

What happens when you assign a value to u.i that's larger than a short can hold? For example, try this:

u.i = 40000;
u.s = 1;

Should the compiler clear out the entire space reserved for u before assigning the short, or should it just write the bytes needed to store the new value? Since it's your responsibility to keep track of how to interpret the value stored in u, storing one type and then reading a different type of a different size seems like a poor plan.

like image 34
Caleb Avatar answered Dec 31 '22 01:12

Caleb