我是C编程语言的新手,我想问一个问题。
整数我在这里是浮动然后f(不知何故)成功代表5.0:
int i = 5;
float f = i; //Something happened here...
但是,如果我们尝试这种方法:
int i = 5;
float f = *(float *)&i;
f不会得到5.0,因为它以“float的方式”解释存储在i中的位。那么编译器在第一种情况下实际上做了多少魔术呢?这似乎是一项非常努力的工作......有人可以指明吗?感谢。
答案 0 :(得分:13)
这是一项努力工作,但任何具有浮点支持的CPU都会提供执行它的指令。
如果您必须为自己将2的补码int
转换为IEEE浮动格式,您会:
n
位(从第一个设置的非符号位后的位开始)到float的有效位数。然而,n
在float
(32位单精度浮点数为23)中有很多有效位。如果int
中有任何剩余的位(即,如果它大于2 24 ),并且在你有空间的那一位之后的下一位是1
,根据运行中的IEEE舍入模式,您可能会或可能不会进行舍入。int
复制到float
。答案 1 :(得分:6)
如果你看看程序集
int i = 5;
000D139E mov dword ptr [i],5
float f = i;
000D13A5 fild dword ptr [i]
000D13A8 fstp dword ptr [f]
fild 是神奇的
答案 2 :(得分:2)
在IA32系统上,编译器将生成以下内容: -
fild dword ptr [i] ; load integer in FPU register, I believe all 32bit integers can be represented exactly in an FPU register
fstp dword ptr [f] ; store fpu register to RAM, truncating/rounding to 32 bits, so the value may not be the same as i
答案 3 :(得分:2)
将int位转换为float
float IntBitsToFloat(long long int bits)
{
int sign = ((bits & 0x80000000) == 0) ? 1 : -1;
int exponent = ((bits & 0x7f800000) >> 23);
int mantissa = (bits & 0x007fffff);
mantissa |= 0x00800000;
// Calculate the result:
float f = (float)(sign * mantissa * Power(2, exponent-150));
return f;
}
答案 4 :(得分:1)
魔力取决于你的平台。
一种可能性是您的CPU有一条特殊指令将浮点数复制到整数寄存器中。
当然有人必须设计这些CPU,所以这并不是对手头算法的真正解释。
平台可能正在使用这样的浮点格式(实际上,为了示例,这是一种定点格式):
[sIIIIFFFF]
其中s
是符号,I
是点之前的部分,F
是点之后的部分,例如(点是虚拟的,仅用于演示)
- 47.5000
[sIIII.FFFF]
在这种情况下,转换几乎是微不足道的,可以使用bithifting来实现:
-47.5000
>> 4
---------------
-47
与此示例中一样,商品C ++实现使用通常称为IEEE Floating Point的浮点表示,另请参阅IEEE 754-1985。这些比定点数字更复杂,因为它们确实指定了形式_s * m n 的简单公式,但是,它们具有明确定义的解释,你可以将它们展现得更合适。
答案 5 :(得分:0)
在几乎所有现代系统中,浮点运算的规范是IEEE754标准。这详细介绍了从内存布局到传播截断和舍入的所有内容。这是一个很大的领域,你常常需要详细考虑科学和工程规划。
答案 6 :(得分:0)
好吧,我刚刚在VC ++下编译了有问题的代码并查看了反汇编:
int i = 5;
00A613BE mov dword ptr [i],5
float f = i;
00A613C5 fild dword ptr [i]
00A613C8 fstp dword ptr [f]