Hacker News new | ask | show | jobs
by thwest 3981 days ago
I was under the impression that C11/C99 only guaranteed that the most recently assigned union member would have an initialized value.
2 comments

From C11: 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.

union { int x; float y; } b; b.y = 10e5; printf("%x\n", b.x);

That behavior is legal and well-defined behavior (up to the implementation-defined nature of representations) under C99 and C11, but not under C89 and earlier. Unfortunately, although it was made legal in C99, C99 did retain the program as an example in its (non-normative) list of undefined behaviors, which doesn't help clear up its legality.

Its status under C++11 and C++14 is much more debatable. I recall (I may have bad memory) that an early draft of C++0x had incorporated new C99 text on unions, which would have made it legal, but the wording of unions changed dramatically when unrestricted unions were introduced, which means that assessing its present legality relies very heavily on how you extend initialization to types like int and float.

Strictly speaking accessing that union both ways ~~~violates the strict aliasing rules~~~ isn't portable. However, it is such a common idiom that GCC and other compilers explicitly allow using unions to get around the strict aliasing rules, so long as the access is always performed through the union.
Type punning by casting through a union is allowed by c99/c11 in that the behavior is unspecified(not undefined) and a footnote clarified the behavior to be the expected.

http://stackoverflow.com/questions/11639947/is-type-punning-...