...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> void func(void) { union { short a[2]; int i; } u; u.a[0]=0x1111; u.a[1]=0x1111; u.i = 0x22222222; printf("%x %x\n", u.a[0], u.a[1]); /* ... */ } |
The C standard states:
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.
The printf()
printf()
behavior in this compliant solution is unspecified, but it is commonly accepted as an implementation extension. (See unspecified behavior 11.)This function typically outputs "2222 2222". " However, there is no guarantee that this will be true, even on implementations that defined the unspecified behavior; values of type short
need not have the same representation as values of type int
.true; the object representations of a
and i
are unspecified and need not be compatible in this way, despite this operation being commonly accepted as an implementation extension. (See unspecified behavior 11.)
Compliant Solution (memcpy)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> #include <string.h> void func(void) { short a[2]; a[0]=0x1111; a[1]=0x1111; int i = 0x22222222; memcpy(a, &i, sizeof a); printf("%x %x\n", a[0], a[1]); } |
Using memcpy for type punning avoids the unspecified behavior of the union
. A good optimizing compiler will recognize the use of memcpy
and will emit code just as fast as the union
approach.
...