float类型数据存储格式释解

执行环境:32位机小端序 Linux version 2.6.18-238.el5 ([email protected]) (gcc version 4.1.2 20080704 (Red Hat 4.1.2-50))

遇到一个问题,误把int数据直接强制转换为float型数据来用,得出的结果完全不认识,看来需要仔细分析一下float及int数据在内存里具体是怎么格式存储的,只有这样才能搞明白中途发生了什么,导致出错。

float fv=52.5;
char *cp=&fv;
printf("%x,%x,%x,%x\n",*cp,*(cp+1),*(cp+2),*(cp+3));

执行输出:0,0,52,42

二进制显示既: 0000 0000  0000 0000 0101 0010 0100 0010 
既然内存里存储格式如此,那么如何转化为float型52.5的呢?

查阅float数据格式:SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM

S:符号位,占1位空间

E:指数位,占8位空间,其值为真实的二进制指数加127得出,为什么加127是IEEE定的。你可以去问他们。

M:底数位,占24位,但实际上值存了23位,小数点前默认为1,所以省出来1位。

 

小端序机器可知

S=0                                                                       --->0代表正,1代表负

E=100 00100                                                       --->132-127=5,真实的指数为5

M=101 0010 0000 0000  0000 0000               --->小数点固定为1则底数为1.101 0010 0000 0000  0000 0000 

好了现在已经将数据按照float格式界定完毕,接下来就是如何转化验证是不是预期所示的52.5

将二进制转为十进制数据:1*2^5+1*2^4+0*2^3+1*2^2+0*2^1+0*2^0+1*2^(-1)+0*.....0*2^(-19)=32+16+4+0.5=52.5

结果如预期。

通过分析可知float的数据存储与int数据存储策略是完全不同的,如人为的将int ivar误当做float 数据用那么,ivar里本身原有的数据位会相应的分配为 S位,E位及M位,结果可想而知。完全就乱了。编译器很傻的这时候。

有个特例既 float 0的存储 指数及底数均为0,但2^0=1,不符合SEM公式,当做特例处理即可,不影响通用性。

你可能感兴趣的:(C)