为什么以下代码的输出是7.00649e-45?

时间:2015-09-09 18:15:13

标签: c++ pointers

这是垃圾值吗? 即使在垃圾价值中,我也从未见过指数。

#include<iostream>
using namespace std;

int main() {
    short s=5;
    float f= * (float*)&s;
    cout<< f << endl;

}

编辑:现在我明白这是你必须了解计算机架构的少数情况之一,即在内存级别实际发生了什么。

3 个答案:

答案 0 :(得分:4)

此代码通过将原始位表示移动到浮点数中将整数值强制转换为浮点值;发生这种情况是因为您将指针short*强制转换为float* - 这不会以任何方式强制转换指向的基础。浮点表示与整数表示不兼容,所以基本上,是的,你得到一个垃圾值。

此外,在典型的x86 / x86_64机器上,short是2个字节,而float是4个字节,因此作为浮点值读出的数字不仅仅是你添加的short值的内容,还有堆栈空间紧接在记忆中。

更多细节(关于浮点表示)

我假设您使用的是小端机器,例如86 / x86_64的。

短值是两个字节。在little-endian编码中,低位字节首先出现,因此十进制值5在内存中看起来像这样:

05 00

浮点值是四个字节。因此,当系统尝试将两个字节作为浮点数加载时,它还必须查看接下来的两个字节。如果你的堆栈还没有到达这么远,那么接下来的两个字节可能是零,所以这就是我们的浮点数看起来像内存中的原始十六进制值:

05 00 00 00

但是,由于您的系统是little-endian,当您真正想要解释此值时,按顺序读取它的方式如下:

00 00 00 05

所以这是浮点值的原始二进制表示。但这些比特代表什么价值?为此,我们必须知道如何解释它们。这将符合IEEE 754标准的单精度浮点数,您可以阅读更多关于on wikipedia的信息。

这种解释的摘要如下:

因此,如果您根据解释浮点数的规则解释给定的位串,则结果值为7.006492321624085e-45,这正是您得到的答案。

一个简单的方法是使用python的“struct”模块:

>>> import struct
>>> struct.unpack('<f', b'\x05\x00\x00\x00')
(7.006492321624085e-45,)

<表示将以下字节解释为little endian,f表示将以下字节解释为float。

请注意,如果您使用的是big-endian计算机,则短表示形式为00 05 00 00,但浮点表示将为00 05 00 00。我们再次通过使用python的struct模块解释位模式,找出它代表的值:

>>> struct.unpack('>f', b'\x00\x05\x00\x00')
(4.5917748078995606e-40,)

>意味着我们这次将它解释为大端)

答案 1 :(得分:2)

可能你的平台碰巧分配了四个字节并用零填充它们除了5以外.5被解释为最不重要的二进制数字。 5 /(2 ^ 149)是7.00649232e-45。

答案 2 :(得分:0)

你想要float f = (float)s,因为你希望得到5.0,或者你真的想要重新解释这些位(这可能与uint32_tfloat有关,这些是相同大小),reinterpret_cast。进行这种类型惩罚的C风格方式是与每种类型的成员建立联合,使用一种类型存储到它,并使用另一种类型从中读取。

你所做的不合法,在某些系统上,它会导致程序崩溃,因为在该CPU上,类型具有不同的内存对齐要求。