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 = (unsign
If you really want to be agnostic about the size of the float type and just return the raw bits, do something like this:
void float_to_bytes(char *buffer, float f) {
union {
float x;
char b[sizeof(float)];
};
x = f;
memcpy(buffer, b, sizeof(float));
}
Then call it like so:
float a = 12345.6789;
char buffer[sizeof(float)];
float_to_bytes(buffer, a);
This technique will, of course, produce output specific to your machine's byte ordering.
The following does not violate the aliasing rule, because it has no use of lvalues accessing different types anywhere
template<typename B, typename A>
B noalias_cast(A a) {
union N {
A a;
B b;
N(A a):a(a) { }
};
return N(a).b;
}
unsigned bar(float x) {
return noalias_cast<unsigned>(x);
}
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.