How can *i
and u.i
print different numbers in this code, even though i
is defined as int *i = &u.i;
? I can only assuming
The disrepancy is issued by -fstrict-aliasing
optimization option. Its behavior and possible traps are described in GCC documentation:
Pay special attention to code like this:
union a_union { int i; double d; }; int f() { union a_union t; t.d = 3.0; return t.i; }
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. So, the code above works as expected. See Structures unions enumerations and bit-fields implementation. However, this code might not:int f() { union a_union t; int* ip; t.d = 3.0; ip = &t.i; return *ip; }
Note that conforming implementation is perfectly allowed to take advantage of this optimization, as second code example exhibits undefined behaviour. See Olaf's and others' answers for reference.