为什么这个 float union 的输出是 NaN?

Why is output of this float union NaN?

在我的 C++ 代码中,我声明了一个联合:

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

然后,我将 byte_data 数组设置为值 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);

作为输出,我得到 NaN。为什么我得不到正常的浮点值?当我传递值时:56、137、33、63。我得到浮点值 0.631000。

测试代码:http://codepad.org/Q8ds1V0F

NaN 一个普通的浮点值,你设置的字节被正确解释为a valid NaN.

话虽如此,自 using a union in this manner has undefined behaviour in C++ 以来,您可以获得输出 "there is no spoon NaN"。您在任何给定时间只能使用工会的一名成员。它不是重新解释转换的捷径!

通过将上述字节写入数组,您将获得 00 00 c0 7f 的内存布局,在 endian, reads as 7fc00000. Interpreting this as an IEEE float 中可以得到

  • 0 的符号(正数,但与 NaN 无关)
  • 0xFF
  • 的指数
  • 0x400000 的尾数(> 0 且设置了最高有效位 → 静默)

这会得到一个(无声的)NaN 值。

至少,这对 C 来说是重要的。在 C++ 中,它没有定义你做什么,但是如果你仍然得到 NaN 作为结果,你的编译器将它视为 C(尽管如此不推荐依赖未定义的行为!)。

如果输出不确定,即无法确定其值(例如 0/0),通常会出现 NaN(不是数字)错误。

但无论如何我不会使用联合(个人不喜欢),当你使用联合时,设置一个成员并提取另一个成员是未定义的行为。

一方面,浮点值基本上被分成位域,有那么多位保存尾数,那么多位保存指数,还有一位保存符号。另一方面,整数只是数字的 base-2 表示。他们的位只是排列不一样。

你可以这样做:

unsigned long int l = byte_data[0] | (byte_data[1] << 8) | (byte_data[2] << 16) | (byte_data[3] << 24);