printf以%d形式输出浮点数的问题

 
float value = 1.0;
printf("value_int = %d\n", value);
 
对于上面的代码,会输出什么结果呢?( 结果是0,当然这跟你的计算机是大端还是小端有关,大小端分析一样,这里是以小端为例)是不是觉得很奇怪,value的浮点数表示形式是 0x3F800000,如果以整形输出,应该也是这个值的十进制表示才对的。

单精度浮点数表示是:1位符号,8位阶码,23位尾数: 1.0的符号位是0,注意1.0的整数位1省略了,所以尾数全是0,而阶码是移码表示,所以是1+127,参考
双精度浮点数表示是:1位符号,11位阶码,52位尾数:如果是double value,则value的表示形式是 0x3FF0000000000000
关于浮点数的机器表示参考: http://zh.wikipedia.org/wiki/IEEE_754 

分析上面代码的汇编实现:(这里是VS下的反汇编代码,关注标红部分及下面的解释就行
float value = 1.0;汇编代码如下:
004113BE   fld1         
//向浮点器特殊寄存器st7(64位)中初始化值为1的浮点数(双精度)     
004113C0   fstp        dword ptr [value]  
//从浮点器特殊寄存器st7中载入数值到value中,注意这里是dword(32位),作了双精度到单精度的转换
 
printf("value_int = %d\n", value);汇编代码如下:
004113C3   fld         dword ptr [value] 
//向浮点器特殊寄存器st7(64位)中存入单精度value
004113C6  mov         esi,esp 
004113C8  sub         esp,8 
004113CB   fstp        qword ptr [esp]
//从浮点器特殊寄存器st7中载入数值(value的双精度)到esp指向的地址中,注意这里是qword(64位),所以不用转换 
004113CE  push        offset string "value_int = %d\n" (415800h) 
004113D3  call        dword ptr [__imp__printf (4182BCh)] 
004113D9  add         esp,0Ch



上面的代码把1的双精度值压入了栈中,而我的计算机又是小端的,那么内存从从低到高字节依次是
00 00 00 00 00 00 F0 3F(即0x3FF0000000000000以字节为单位倒置

当printf检测到%d要输出整形时,取到的值是00 00 00 00,所以这就不难理解为什么结果是0了。如果是大端,那么输出0x3FF00000的十进制值。

如果对printf实现不是很了解,可以参考http://blog.csdn.net/fzp218/article/details/7375427

 


总结:
适当知道点汇编还是挺重要的,像这种在高级语言层面看不清的问题,一看汇编就明了了。


原文地址:https://www.cnblogs.com/javawebsoa/p/3097646.html