Stefan's Blog

Type punning with unions

Sometimes you might want to reinterpret a value of one type as value of another type. For example you might have an integer parameter, but you know that it actually contains a float value.

Let’s assume the integer was large enough to store the float somehow, and now you want to get the value back. If you follow wikipedia you might do something like this:

1
2
3
4
5
6
7
8

floatget_float(inti){union{inti;floatf;}x;x.i=i;returnx.f;}

Usually this works fine; as long as you access the values directly through the union member probably no compiler will screw this up. (There are various claims whether this is actually supposed to work in different language versions and C vs C++.)

But if you start using pointers (or references in C++) this can fail very fast:

Although in return0i and f refer to the same memory location, and the write to f comes after the write to i, the compiler will ignore the write to f. This is called “strict aliasing”; the compiler assumes that a write to a float reference will not modify any integers, and therefore the written integer value is still present.

Even inlining doesn’t help the compiler to see it, and it also doesn’t print a warning.