Say I have a float that I want to interpret as an unsigned int for some bit-twiddling (let’s assume sizeof(float) == sizeof(int) for now). Now there are various ways that “work”, for example:
float f = 0.5f;
unsigned int u;
u = * (unsigned int*) (&var); /* works in most compilers */
union {
float f;
unsigned int u;
} uconv;
uconv.f = f;
u = uconv.u; /* works in most compilers */
Now I don’t know the standard by heart, but IIRC the first is undefined behaviour thanks to the strict aliasing rule and I heard that the latter is undefined behaviour too.
So what is the correct, defined way to interpret the value of one type as if it was another type?
Please add to your answer whether it works for C89, C90, C99 or even C11.
In general, the correct way is to cast the variable’s address to
void*,char*orunsigned char*, because any other pointer cast may cause undefined behavior (indeed, because of strict aliasing).int*andfloat*are incompatible pointer types.When the
sizeofboth types is the same, the following will work:The value that you get is obviously implementation-defined, since it depends on how both
intandfloatare represented in memory.Strict aliasing has been around since C89.
EDIT: seems I was wrong previously about the
unionhack causing UB. The relevant part of the C11 draft states:— Foonote 95 to 6.5.2.3 Structure and union members