printf格式串中的%f到底是float还是double?实验来证明!

问:有人告诉我不能在printf中使用%lf。为什么printf()用%f输出double型,而scanf却用%lf呢?

答:printf的%f说明符的确既可以输出float型又可以输出double型。 根据"默认参数提升"规则((Default Argument Promotion):
  如果表达式是不用原型控制的函数调用中的参数,或表达式显示为原型参数表中"..."部分的参数,则先转换表达式的值之后再传递到函数中。 char 和 short int 晋级到 int, float 晋级到 double。)float型会被提升为double型。因此printf()只会看到双精度数。(所以:在vc6.0下,short m=-1;printf("%d",m);屏幕上应该是ffffffff,而不是ffff)

对于scanf,情况就完全不同了,它接受指针,这里没有类似的类型提升。(通过指针)向float存储和向double存储大不一样,因此,scanf区别%f和%lf。

(严格地讲,%lf在printf下是未定义的,但是很多系统可能会接受它。要确保可移植性,就要坚持使用%f。)
 
int  a  =   0 , b  =   0 ;
printf(
" %f, %d " , a, b);
可是运行结果并不尽如人意,%f字段输出了0,%d字段输出一个较大的数据。

因为我最近刚阅读了浮点数的内存表示方法,所以对上述代码做出解释如下:
%f为double类型,需要两个字节表示,所以,printf在遇到%f时即将a,b的两个整型数据都读了去,而到了需要输出%d的时候,只能读取b的下一个单元,自然不是所期望的数据了。

但是有朋友说%f是float类型,%lf才是double类型,具此我特意查阅了MSDN和Linux man手册,均没有发现此类描述,在linux man手册中,说明%lf为long double类型。
为了说明问题,我又做了几个实验:

实验一,检查%f需要读取几个字节
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> int  a = 0 , b = 0 , c = 5 ;
printf(
" %f,%d\n " , a, b, c);
输出结果:
0,5
结论:%f读取8个字节,即两个整型大小

实验二,检查%lf需要读取几个字节
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> int  a = 0 , b = 0 , c = 5 ;
printf(
" %lf,%d\n " , a, b, c);
输出结果:
0,5
结论:%lf也读取8个字节(也许和机器位宽有关,我是32位的机器)

实验三,检查printf读取float类型数据
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> float  a = 0.0f ;
int  b = 5 ;
printf(
" %f,%d\n " , a, b);
输出结果:
0.0,5
结论:float类型只占4个字节的数据,但前面实验一已经证明%f会读8个字节,即double类型的宽度,所以,编译器在将float类型参数入栈的时候,事先转换成了double类型。

实验四,再次证明实验三的结论
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> float  a = 0.0f ;
int  b = 5 ;
printf(
" %d,%d,%d\n " , a, b);
输出结果:
0,0,5
结论:a在入栈的时候,占了8个字节。

以上4步,我觉得可以证明 %f是按double类型输出的了,另外,我也知道了float类型在作为参数进行传递的时候,编译器会先将它转换成double类型。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值