深度解析为何printf("%f",45);结果为零

简介: 如题,出现这种情况的原因有两个: 1、整形数和浮点数在内存中的存储格式和布局不同(理解浮点数的内存布局和表示方式,请参考:http://blog.csdn.net/songjinshi/article/details/7753777) 2、printf在进行参数入栈时是根据实参的类型进行入栈,而不是根据格式化字符中指定的类型,具体入栈过程如以下所示。

如题,出现这种情况的原因有两个:

1、整形数和浮点数在内存中的存储格式和布局不同(理解浮点数的内存布局和表示方式,请参考:http://blog.csdn.net/songjinshi/article/details/7753777

2、printf在进行参数入栈时是根据实参的类型进行入栈,而不是根据格式化字符中指定的类型,具体入栈过程如以下所示。所以造成入栈实参的类型和实际函数使用的类型不匹配(关键是所占内存的大小不同),所以在具体的解析中就会出现如题所说的结果,因为整形的内存布局在被解析为浮点数时会非常小,因为整形本来是4个字节存储,而被解析为8个字节的浮点数,所以所得的值会非常小,正如浮点数的的表示:非规格化:当E的二进制位全部为0时,N为非规格化形式。

  注意,此时小数点左侧的隐含位为0。 为什么e会等于(1-bias)而不是(-bias),这主要是为规格化数值、非规格化数值之间的平滑过渡设计的。后文我们还会继续讨论。

  有了非规格化形式,我们就可以表示0了。把符号位S值1,其余所有位均置0后,我们得到了 -0.0; 同理,把所有位均置0,则得到 +0.0。非规格化数还有其他用途,比如表示非常接近0的小数,而且这些小数均匀地接近0,称为“逐渐下溢(gradually underflow)”属性。


下面贴出两段反汇编代码,解析参数如何入栈:

    printf("%f",45);
00405028  mov         esi,esp
0040502A  push        2Dh  
0040502C  push        offset _ORDER_SERVER_ADDRESS-0ACh (43F2ACh)
00405031  call        dword ptr [__imp__printf (43C124h)]
00405037  add         esp,8

    printf("%f",d);(d为整形变量
00405028  mov         esi,esp
0040502A  mov         ecx,dword ptr [d]
0040502D  push        ecx  
0040502E  push        offset _ORDER_SERVER_ADDRESS-0ACh (43F2ACh)
00405033  call        dword ptr [__imp__printf (43C124h)]
00405039  add         esp,8
0040503C  cmp         esi,esp
0040503E  call        _RTC_CheckEsp (439760h)

    double a=5,c;
    float b;
    int d=0x40a00000,y=6;
    int *p;
    char s=5;

    p=&d;

    b=(float)a;

    printf("%f,%f,%f,%f,%f,%f,%d",b,c,(float)d,s,(float)s,y,y);

00405028  mov         esi,esp

0040502A  mov         ecx,dword ptr [y]

0040502D  push        ecx  

0040502E  mov         edx,dword ptr [y]

00405031  push        edx  

00405032  movsx       eax,byte ptr [s]

00405036  mov         dword ptr [ebp-34h],eax

00405039  fild        dword ptr [ebp-34h]

0040503C  sub         esp,8

0040503F  fstp        qword ptr [esp]

00405042  movsx       ecx,byte ptr [s]

00405046  push        ecx  

00405047  fild        dword ptr [d]

0040504A  sub         esp,8

0040504D  fstp        qword ptr [esp]

00405050  sub         esp,8

00405053  fld         qword ptr [c]

00405056  fstp        qword ptr [esp]

00405059  fld         dword ptr [b]

0040505C  sub         esp,8

0040505F  fstp        qword ptr [esp]

00405062  push        offset _ORDER_SERVER_ADDRESS-0C4h (43F2ACh)

00405067  call        dword ptr [__imp__printf (43C124h)]

0040506D  add         esp,30h

00405070  cmp         esi,esp

00405072  call        _RTC_CheckEsp (439780h)


目录
相关文章
|
2月前
|
程序员 编译器 C语言
用printf函数输出数据
用printf函数输出数据
16 2
|
2月前
|
C语言
使用printf函数输出数据
在C语言中,printf函数是一个常用的标准库函数,用于在控制台输出格式化的字符串和数据。它允许我们按照指定的格式输出各种类型的数据,包括整数、浮点数、字符和字符串等。
8 0
|
10月前
|
存储 Serverless
strlen函数解析与模拟实现
strlen函数解析与模拟实现
strlen函数解析与模拟实现
|
10月前
|
算法 Java API
【算法】字符串转int类型思路及代码
【算法】字符串转int类型思路及代码
110 0
|
12月前
|
编译器 C语言 C++
模拟实现strcmp
模拟实现strcmp
|
XML C语言 数据格式
C基础——使用printf打印各种数据类型的方式(示例)
C基础——使用printf打印各种数据类型的方式(示例)
572 0
C基础——使用printf打印各种数据类型的方式(示例)
|
编译器 C语言 C++
scanf函数不能运行(VS2019)(解决方案)
直接放在拷贝文档里,以后每次建立新项目时就会自动添加这行代码(详情请看本人空间的:VS文件初始化教程)
171 0
scanf函数不能运行(VS2019)(解决方案)
|
前端开发 NoSQL 测试技术
优雅的输出错误-assert
优雅的输出错误-assert
133 1
优雅的输出错误-assert
|
Windows
3dMax建模笔记(一):介绍3dMax和创建第一个模型Hello world
三维模型,虽然淘宝上一抓一大把,但是三维开发人员最好还是具备一定基础的建模能力。本文用hello world模型描述基本的3dMax建模流程。
3dMax建模笔记(一):介绍3dMax和创建第一个模型Hello world
|
Windows
printf花式输出
printf花式输出
127 0
printf花式输出

热门文章

最新文章