Note that the C99 (I'm not up on C11 yet) standard specifically allows type-punning through the use of unions (and disallows it in essentially all other cases except when one type is a character type).
Also, there seems to be some confusion about storing and loading pointers, when the standard speaks to this as well; roughly: a pointer which is converted to a "large enough" integer type will point to the same object when converted back. It is permissible for an implementation to not provide a large enough integer type, but excepting that, the behavior is well defined.
C89 prohibited union type-punning. C99 allowed it, but mistakenly left the prohibition in the (non-normative) list of undefined behaviors. C11 did rectify the list.
Also, there seems to be some confusion about storing and loading pointers, when the standard speaks to this as well; roughly: a pointer which is converted to a "large enough" integer type will point to the same object when converted back. It is permissible for an implementation to not provide a large enough integer type, but excepting that, the behavior is well defined.