先看一道练习题:
int main()
{
int n = 9;
float* pFloat = (float*)&n;
printf("n的值为:%d\n", n);
printf("*pFloat的值为:%f\n", *pFloat);
*pFloat = 9.0;
printf("num的值为:%d\n", n);
printf("*pFloat的值为:%f\n", *pFloat);
return 0;
}
定义一个整形变量n=9,
定义一个浮点数指针用来存放n的地址,n的地址应为int*类型,所以强制类型转换为float*类型
以%d形式(整形方式)打印n
以%f形式(浮点数形式)打印n
对其指针进行解引用,将n变为9.0
继续
以%d形式(整形方式)打印n
以%f形式(浮点数形式)打印n
简单来说代码分别用整形和浮点型的方式对其进行赋值,然后再以整形和浮点数类型分别拿出来
那结果会是什么呢?
9,9.0,9,9.0???
均不是,结果是:
为什么呢?
因为浮点数和整数的存储方式在内存中完全不同!!!
浮点数在内存中的存储:
1.1浮点数家族包括:
float
double
long double
浮点数表示的数据范围在float.h中定义
那浮点数是怎么储存的呢?
1.2储存规则
国际标准IEEE(电气和电子工程协会)754规定,任意一个二进制浮点数F都可以表示成下面的形式:
(-1)^S * M * 2^E
(-1)^S:表示符号位,当S=0,F为正数,S=1,F为负数
M:表示有效数字,大于等于1,小于2.
2^E:表示指数位
由于M写成科学计数法,必定为1.xxxxx的形式,其中xxxxx为小数部分,
所以标准规定,M在存储的时候只保留小数部分,也就是xxxxx部分,比如5.5
二进制为101.1,写成科学计数法M为1.011,在保存的时候将会舍弃掉1,只保留011.
在读取的时候再把第一位的1加上,如此做可以节省一位有效数字,精度将会提高。
指数E在存储中定义为一个无符号整数
也就是说在存储5.5时,E=2,但是在存储中8个比特位并不是存储的00000010
而是存储的E+127也就是说存储的为2+127=129,转化为2进制为 10000001
M实际存储为011,不够23个比特位,补0
所以5.5在内存中的储存为:
在这说了大半天,到底是不是呢?
我们验证一下
内存中确实是这样存储的
1.3读取规则:
在读取的时候要特别注意E的读取
E不全为0或不全为1
浮点数的指数E等于1-127(或者1-1023)即为真实值,
E全为1
接下来我们再次分析开篇的问题