I am trying to extract the bits from a float without invoking undefined behavior. Here is my first attempt:
unsigned foo(float x) { unsigned* u = (unsigned*)&x; return *u; }
As I understand it, this is not guaranteed to work due to strict aliasing rules, right? Does it work if a take an intermediate step with a character pointer?
unsigned bar(float x) { char* c = (char*)&x; unsigned* u = (unsigned*)c; return *u; }
Or do I have to extract the individual bytes myself?
unsigned baz(float x) { unsigned char* c = (unsigned char*)&x; return c[0] | c[1] << 8 | c[2] << 16 | c[3] << 24; }
Of course this has the disadvantage of depending on endianness, but I could live with that.
The union hack is definitely undefined behavior, right?
unsigned uni(float x) { union { float f; unsigned u; }; f = x; return u; }
Just for completeness, here is a reference version of foo
. Also undefined behavior, right?
unsigned ref(float x) { return (unsigned&)x; }
So, is it possible to extract the bits from a float (assuming both are 32 bits wide, of course)?
EDIT: And here is the memcpy
version as proposed by Goz. Since many compilers do not support static_assert
yet, I have replaced static_assert
with some template metaprogramming:
template <bool, typename T> struct requirement; template <typename T> struct requirement<true, T> { typedef T type; }; unsigned bits(float x) { requirement<sizeof(unsigned)==sizeof(float), unsigned>::type u; memcpy(&u, &x, sizeof u); return u; }
About the only way to truly avoid any issues is to memcpy.
unsigned int FloatToInt( float f ) { static_assert( sizeof( float ) == sizeof( unsigned int ), "Sizes must match" ); unsigned int ret; memcpy( &ret, &f, sizeof( float ) ); return ret; }
Because you are memcpying a fixed amount the compiler will optimise it out.
That said the union method is VERY widely supported.
The union hack is definitely undefined behavior, right?
Yes and no. According to the standard, it is definitely undefined behavior. But it is such a commonly used trick that GCC and MSVC and as far as I know, every other popular compiler, explicitly guarantees that it is safe and will work as expected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With