前言
在前一节中,讲述了整型数据在内存中的存储方式以及大小端字节序,在这一节主要讲述浮点型在内存中的存储方式。
一、浮点型数据在内存中的存储
1.例子
我们先来看一段代码:
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;
}
我们第一次看到这个代码,可能会认为会输出:
9
9.000000
9
9.000000
实际上输出的是
通过这个结果,我们应该就可以知道浮点型在内存中的存储方式和整型在内存中的存储方式是不同的,那浮点型数据在内存中是怎样存储的呢。
2.存储方式
在C语言中浮点型在内存中的存储方式是按照IEEE754标准:
任意一个二进制浮点数V可以表示成下面的形式:
拿一个数举例,比如说5.5
那么它在内存中是如何存储的呢?
按照标准,对于32位浮点数,最高的一位是符号位,接着8位是指数E,最后23位是有效数字M。
对于64位浮点数,最高的一位是符号位,接着11位是指数E,最后的52位是有效数字M。
其中IEEE754标准对于E和M还有些特别的要求。
前面提过,1<=M<2,也就是说M可以写作1.XXXXX的形式,其中XXXXX是小数部分。因为我们默认第一位数总是1,也就是小数点前的数为1,所以在保存的时候可以把1省略,只保留小数点后的数,这样从原来只能保存23位,到可以保存到24位,增加了有效数字位数。
对于指数E,首先在标准中规定E是无符号整数。这意味着,E为8位,则其取值范围为0-255,E为11位,取值范围为0-2047。但科学计数法中,E可以为负数。所以标准规定,保存E的时候要增加一个中间值,对于8位数的E增加127,对于11位的E增加1023。
所以5.5在内存中的表示方式为:
3.指数E从内存中取出的三种情况
E不全为0也不全为1
这时浮点数采用下列规则表示:
指数E的值减去127,得到真实值,再将有效数字M加上第一位的1(存储在内存中的是小数部分)。
E全为0
对于这种情况,规定E的值为1-127(或者1-1023)作为真实值。
有效数字M不再加上第一位的1,而是直接还原为0.XXXXXX的小数。这样做是为了表示±0,以及接近于0的很小的数字。
E全为1
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);
4.解释上面的例子
缺陷
浮点型数据在内存中的存储并不总是精确的,比如1.3在内存中就不能精确表示,因为0.3不能用2进制明确的表示出来,所以switch语句不能使用浮点型数据。