Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is output of this float union NaN?

In my C++ code I have declared a union:

typedef union U_FloatParse {
    float float_data;
    unsigned char byte_data[4];
} U_FloatConvert;

Then, I set the byte_data array to the values 0, 0, 192, 127:

U_FloatConvert depth_data;

depth_data.byte_data[0] = 0;
depth_data.byte_data[1] = 0;
depth_data.byte_data[2] = 192;
depth_data.byte_data[3] = 127;

printf("\n\nFloat = %f\n\n", depth_data.float_data);

As output I get NaN. Why don't I get a normal float value? When I pass the values: 56, 137, 33, 63. I get the float value 0.631000.

Test code: http://codepad.org/Q8ds1V0F

like image 607
moffeltje Avatar asked Dec 14 '22 01:12

moffeltje


2 Answers

By writing the said bytes into the array, you get a memory layout of 00 00 c0 7f, which, in little endian, reads as 7fc00000. Interpreting this as an IEEE float gives you

  • a sign of 0 (positive, but irrelevant for NaN)
  • an exponent of 0xFF
  • a mantissa of 0x400000 (> 0 and has the most significant bit set → silent)

which gets you a (silent) NaN value.

At least, this counts for C. In C++, it is not defined what you do, but if you nevertheless get NaN as a result, your compiler treats it if it was C (not recommended nevertheless to rely on undefined behaviour!).

like image 64
glglgl Avatar answered Dec 26 '22 16:12

glglgl


NaN is a normal float value, and the bytes you set are correctly interpreted as a valid NaN.

That being said, you could have got the output "there is no spoon NaN", since using a union in this manner has undefined behaviour in C++. You may only use one of the union's members at any given time. It's not a shortcut for reinterpret-casting!

like image 25
Lightness Races in Orbit Avatar answered Dec 26 '22 14:12

Lightness Races in Orbit