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:

#include <cstdio>
#include <cstring>

inline int float_to_int(float f) {
#if NUM == 1
    return *(int*)&f;
#elif NUM == 2
    return *(int*)(char*)&f;
#elif NUM == 3
    return *(int*)(void*)&f;
#elif NUM == 4
    return *reinterpret_cast<int*>(&f);
#elif NUM == 5
    union { float f; int i; } u;
    u.f = f;
    return u.i;
#elif NUM == 6
    int i;
    ((char*)&i)[0] = ((char*)&f)[0];
    ((char*)&i)[1] = ((char*)&f)[1];
    ((char*)&i)[2] = ((char*)&f)[2];
    ((char*)&i)[3] = ((char*)&f)[3];
    return i;
#elif NUM == 7
    int i;
    memcpy(&i, &f, 4);
    return i;

int main() {
    float f = 1.0;
    printf("%d: %08x\n\n", NUM, float_to_int(f));

(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:

$ for n in 1 2 3 4 5 6 7; do ( g++-4.3.1 -O2 -Wall -DNUM=$n float-aliasing.cpp && ./a.out ); done
float-aliasing.cpp: In function ‘int float_to_int(float)’:
float-aliasing.cpp:6: warning: dereferencing type-punned pointer will break strict-aliasing rules
1: b7fa8050

float-aliasing.cpp: In function ‘int float_to_int(float)’:
float-aliasing.cpp:8: warning: dereferencing type-punned pointer will break strict-aliasing rules
2: b7f3c050

float-aliasing.cpp: In function ‘int main()’:
float-aliasing.cpp:10: warning: likely type-punning may break strict-aliasing rules: object ‘*{unknown}’ of main type ‘int’ is referenced at or around float-aliasing.cpp:10 and may be aliased to object ‘f’ of main type ‘float’ which is referenced at or around float-aliasing.cpp:33.
3: b7f9f050

float-aliasing.cpp: In function ‘int float_to_int(float)’:
float-aliasing.cpp:12: warning: dereferencing type-punned pointer will break strict-aliasing rules
4: b7f30050

5: 3f800000

6: 3f800000

7: 3f800000

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.