Dangers of float/int aliasing
This page is an extension of this post on aliasing. In particular, that thread includes several suggestions of code that is undefined according to the standards, which can cause real errors (at least in GCC).
The following example includes various ways of converting a float’s bytes into an int:
inline int
int
(This assumes sizeof(int) == sizeof(float) == 4
. Only one of the sections of code is compiled each time, to prevent interference that obscures the results.)
The printed output should be 3f800000
in every case. Compiling with g++ -O1
, that is indeed the output.
But g++ -O2
gives very different results:
; do ( && ); done
)
)
)
)
The first four cases all produce entirely bogus output (which is permitted because the code is relying on undefined behaviour).
GCC 4.2 doesn’t warn about the third case – that warning is new in 4.3 – but it still produces bogus output.
In the final case, the memcpy
function call is optimised away entirely.
Even if the float is not a compile-time constant, the compiler just generates code to store
the value into memory (fstps
) then loads it back into an integer register (movl
).
So if you want a float_to_int
that has safe, portable, well-defined behaviour
(at least to the extent that the integer representation of floats is portable and well-defined),
and you don’t want to worry about eager compilers breaking your code, use memcpy
.