| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 5412 人关注过本帖
标题:printf用%d打印float型数据剖析
只看楼主 加入收藏
lxsjzbd
Rank: 4
来 自:河北省
等 级:业余侠客
帖 子:97
专家分:258
注 册:2012-3-31
结帖率:100%
收藏
 问题点数:0 回复次数:8 
printf用%d打印float型数据剖析
首先声明对于printf参数求值顺序因编译器不同而不同,在此就不说了;
#include<stdio.h>
int main(void)
{
     float i=125.0;
     printf("%d\n",i);
     return 0;
}
该程序输出0,相信和我一样还处于整天面对黑窗口的鸟哥们,都遇过吧;

第一,先说一下printf处理参数的原理。因为该函数的实现用的是可变参数,所以他并不知道你会输入多少参数,而是先按参数从右到左进行压栈,最后把格式化字符串压入栈,然后根据格式化字符串中%c、%d等等,顺序从压栈倒序获取数据,他会一直认为你输入了足够的参数;例如:printf("%d%d",i);对于后边的%d则是会从上级压栈中读取数据,此处就是main()了,当然都是垃圾数据了,会随编译器不同而不同。

[ 本帖最后由 lxsjzbd 于 2012-11-26 17:55 编辑 ]
搜索更多相关主题的帖子: 打印 include return 编译器 
2012-11-26 17:10
lxsjzbd
Rank: 4
来 自:河北省
等 级:业余侠客
帖 子:97
专家分:258
注 册:2012-3-31
收藏
得分:0 
晚上补上
2012-11-26 17:17
lxsjzbd
Rank: 4
来 自:河北省
等 级:业余侠客
帖 子:97
专家分:258
注 册:2012-3-31
收藏
得分:0 
第二,(尊重原版摘抄自http://)就的说一下浮点数在内存中的存储方式了。任何数据在内存中都是以二进制的形式存储的,例如一个short型数据1156,其二进制表示形式为00000100 10000100.则在intel CPU架构的系统中,存放方式为10000100(低地址单元)00000100(高地址单元),因为intel CPU的架构是小端模式。但是对于浮点数在内存是如何存储的?目前所有C/C++编译器都是采用IEEE所制定的标准浮点格式,即二进制科学表示法。
    在二进制科学表示法中,S=M*2^N主要由三部分构成:符号位+阶码(N)+尾数(M)。对于float型数据,其二进制右32位,其中符号位1位,阶码8位,尾数23位;对于double型数据,其二进制为64位,阶码11位,尾数52位。
        31    30-23    22-0
float  符号位  阶码    尾数
        63    62-52    51-0
double 符号位  阶码     尾数

符号位:0表示正,1表示负;
阶码:这里阶码采用移码表示,对于float型数据其规定偏置量127,阶码有正有负,对于8位二进制,则其表示范围-128-127,double型规定为1023,其表示范围为-1024-1023.比如对于float型数据,若阶码的真实值为2,则加上127后为129,其阶码表示形式为10000010
尾数:有效数字位,即部分二进制位(小数点后边的二进制位),因为规定M的整数部分恒为1,所以这个1就不进行存储了。
2012-11-26 17:40
yaobao
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:蒙面侠
威 望:4
帖 子:1854
专家分:4121
注 册:2012-10-25
收藏
得分:0 
顶一下

认认真真的学习,踏踏实实的走路:戒骄戒躁!!!
2012-11-26 17:46
lxsjzbd
Rank: 4
来 自:河北省
等 级:业余侠客
帖 子:97
专家分:258
注 册:2012-3-31
收藏
得分:0 
下面举例说明:
float型数据125.5转换为标准浮点格式
125二进制表示形式为1111101,小数部分表示为二进制为1,则125.5二进制表示为1111101.1,由于规定尾数的整数部分恒为1,则表示为1.1111.11*2^6,阶码为6,加上127为133,则表示为10000101,而对于尾数将整数部分1去掉,为1111011,在其后边补0使其位数达到23位,则为1111011 00000000 00000000
则其二进制表示形式为
01000010 11111011 00000000 00000000
则在内存中存放方式为:
00000000   低地址
00000000
11111011
01000010   高地址
那么对于本程序值为什么是0呢,因为函数进行了类型转换把float转换为double了。
同理:125二进制表示形式为1111101,小数部分表示为二进制为1,则125.5二进制表示为1111101.1,由于规定尾数的整数部分恒为1,则表示为1.1111.11*2^6,阶码为6,加上1023为1029,则表示为10000000101,而对于尾数将整数部分1去掉,为1111011,在其后边补0使其位数达到52位,则为1111 01100000 00000000 00000000 00000000 00000000 00000000
则其二进制表示形式为
01000000 01011111 01100000 00000000 00000000 00000000 00000000 00000000
则在内存中存放方式为:
00000000   低地址
00000000
00000000
00000000
00000000   
01100000
01011111
01000000  高地址
因此输出时会输出低地址的4个字节0;
如果printf("%d%d",i);那么第二个%d输出1079984128,该数的二进制是100000010111110110000000000000正好是高地址的4个字节
2012-11-26 17:55
lxsjzbd
Rank: 4
来 自:河北省
等 级:业余侠客
帖 子:97
专家分:258
注 册:2012-3-31
收藏
得分:0 
纯手打,如果有不足望各位友友指正
2012-11-26 17:58
mateng
Rank: 1
等 级:新手上路
帖 子:7
专家分:6
注 册:2012-11-22
收藏
得分:0 
挺好
2012-11-26 19:26
zxr_fx
Rank: 1
等 级:新手上路
帖 子:28
专家分:7
注 册:2012-11-21
收藏
得分:0 
看不懂,只学到循环,不过也遇到过类似情况,很费解,望楼主用易懂的语言解释一下

菜鸟成长中
2012-11-26 21:18
星星的故乡
Rank: 1
等 级:新手上路
帖 子:28
专家分:0
注 册:2013-10-29
收藏
得分:0 
佩服楼主,谢谢楼主;
如果i=0.25的话,尾数部分的整数就不是1,而是0了,这样的话该如何处理呢,谢谢啦
2013-10-29 21:15
快速回复:printf用%d打印float型数据剖析
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.015385 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved