Some are saying it's working fine. Some don't like it.
Does anybody have an example where union type punning of uint32 and uint8[4] behave different than expected?
Under a quite relaxed set of constraints, that specific example of type punning is perfectly fine.
The only condition to verify is that
sizeof(uint32_t) == 4.
Just to make sure, let's see how I derive this conclusion, from the C99 standard:
First of all, we are guaranteed that there are no padding bits or bytes:
Both uint8_t and uint32_t are exact-width integer types.
As a typedef, uint8_t it cannot be smaller than the smaller integer type, char, and is unsigned so there's no alternative for it to be anything else that unsigned char (7.18.1.1), with size 1 by definition.
Chapter 6.2.6.1 (Representation of types - General) states in §4:
Values stored in non-bit-field objects of any other object type consist of n × CHAR_BIT
bits, where n is the size of an object of that type, in bytes. The value may be copied into
an object of type unsigned char [n] (e.g., by memcpy); the resulting set of bytes is
called the object representation of the value.
This is a guarantee that any object value can be represented in a sequence of unsigned chars. It does not guarantee, in general, that any value of the sequence corresponds to a valid object (trap representations), but in our case:
- There is no padding
- All the bit combination in an uint32_t (sized 4) are then a valid value, as a consequence of 6.2.6.2 Integer types, §4
So no trap representation is possible.
Similar consideration can be made in other cases, as an example, if instead of uint32_t we consider int32_t, we must add another constraint:
The implementation must use two's complement integer representation.
If this is not verified (one's complement or sign magnitude) the bit pattern for negative 0 might be a trap representation.
As both the representation and the trap status of negative 0 are implementation-defined, they must be documented by the compiler.
Now, endianness is a different matter...but still must be documented, as is part of the implementation-defined behaviour (J.3.13 Architecture).
EtA: It must be said that if type punning is done to "optimize" the code,
it is mostly a wasted effort.
Much better use explicit shifts: if they match endiannes, they are optimized away, if they do not, type punning would introduce a bug.