`
mmdev
  • 浏览: 12956812 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多

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

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)


分享到:
评论

相关推荐

    printf函数的格式字符g的用法1

    printf 函数的格式字符 g 的用法%g 格式输出:以%f 或%e 格式符中输出宽度较短的形式,并去掉小数点后的无效 0,且最多保留 6 位有效数字(如果%

    C语言printf输出格式的汇总

    本资源包括所有的printf函数的使用方法和方式,并对相关内容进行了汇总,具有极好的实用性

    C语言Printf格式,调试最好的助手!

    C中格式字符串的一般形式为: %[标志][输出最小宽度][.精度][长度]类型, 其中方括号[]中的项为可选项。

    Shell编程-字符截取命令-printf命令

    Shell编程-字符截取命令-printf命令

    C51 单片机 利用printf函数输出字符串

    工程是keil2. 简单的利用C51单片机,实现了printf函数输出字符串,数字等。 找了好多资料,然后自己总结了下,实现了printf函数的应用。 有了printf函数,你就可以像VC中一样实现输出了。

    2008-2009学年c语言试题

    printf("%f",x); else printf("%f",-x); B) if(x>0) {x=x+1;printf("%f",x);} else printf("%f",-x); C) if(x>0); {x=x+1;printf("%f",x);} else printf("%f",-x); D) if(x>0) {x=x+1;printf("%f",x)} else printf(...

    STM32F469 重定向printf到USB CDC

    将STM32F469的printf重定向到其USB CDC上的工程源码(Keil5),可以直接使用USB当串口调试工具,printf格式化输出。

    STM32F407用IAR编译的串口通信例程,带printf函数

    STM32F407用IAR编译的串口通信例程,带printf函数,有需要的朋友可以下载去参考,祝大家学习愉快

    GD32 Printf重定向

    使用GD32的USART0来实现Printf输出功能

    printf

    _printf ( " %c " , " H " ); _printf ( " %s " , " Bienvenue chez vous " ); _printf ( " %r " , " Holberton " ); _printf ( " %R " , " adrien " ); // ... 将显示: H Bienvenue chez vous notrebloH nqevra ...

    基于正点原子阿波罗STM32F429+STM32CubeMX实现串口printf

    基于正点原子阿波罗STM32F429+STM32CubeMX实现串口printf.就是最基本的程序.利用STM32CubeMX建立一个程序,打开串口,然后配置为printf发送数据.

    printf源代码分析

    printf()函数的调用格式为: printf("<格式化字符串>", <参量表>)。 格式输出,它是c语言中产生格式化输出的函数(在 stdio.h 中定义)。用于向终端(显示器、控制台等)输出字符。格式控制由要输出的文字和数据格式...

    Printf输出格式.

    printf输出格式 格式代码 A ABC ABCDEFGH %S A ABC ABCDEFGH %5S ####A ##ABC ABCDEFGH %.5S A ABC ABCDE %5.5S ####A ##ABC ABCDE % - 5S A#### ABC## ABCDEFGH

    STM32F407-printf-keil5.zip

    keil5针对串口1的充定义,可以打印printf数据,

    printf的源代码

    printf的源代码,了解printf具体的代码。printf的源代码,了解printf具体的代码。

    完全printf解析借鉴.pdf

    完全printf解析借鉴.pdf

    自己实现的printf.cpp

    自己实现的printf,只用putchar()打印输出。实现了所有格式输出(%d、%f、%s、%e、%E、%g、%G、%o、%u、%i、%x、%X),一些细节例如最大宽度、精度、左对齐、右对齐和标准八进制、十六进制输出等都已经实现。

    printf函数输出格式

    必须用与数据类型相匹配的输出格式,才能把数据...C语言的printf函数提供了丰富的输出格式,printf的格式控制的完整格式由前导字符与格式字符构成,即: %前导字符格式字符 其中%:表示格式说明的起始符号,不可缺少。

    scanf/printf中%的使用方法

    标准输入输出函数%[]和%n说明符的使用方法 scanf fscanf,均从第一个非空格的可显示字符开始读起!

Global site tag (gtag.js) - Google Analytics