首先,引入一段代码
#include <stdio.h>
int main()
{
int n = 9;
float *pFloat = (float *)&n;
printf("n = %d\n", n);
printf("*pFloat = %f\n", *pFloat);
*pFloat = 9.0;
printf("n = %d\n", n);
printf("*pFloat = %f\n",*pFloat);
return 0;
}
结果
这个结果说明:整型与浮点型在内存中的存储方式不同
浮点数类型的规定
IEEE二进制浮点数算术标准(IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用。这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denormal number)),一些特殊数值(无穷(Inf)与非数值(NaN)),以及这些数值的“浮点数运算符”;它也指明了四种数值舍入规则和五种例外状况(包括例外发生的时机与处理方式)。
IEEE 754规定了四种表示浮点数值的方式:单精确度(32位)、双精确度(64位)、延伸单精确度(43比特以上,很少使用)与延伸双精确度(79比特以上,通常以80位实现)。只有32位模式有强制要求,其他都是选择性的。大部分编程语言都有提供IEEE浮点数格式与算术,但有些将其列为非必需的。例如,IEEE 754问世之前就有的C语言,有包括IEEE算术,但不算作强制要求(C语言的float通常是指IEEE单精确度,而double是指双精确度)。
该标准的全称为IEEE二进制浮点数算术标准(ANSI/IEEE Std 754-1985),又称IEC 60559:1989,微处理器系统的二进制浮点数算术(本来的编号是IEC 559:1989)。后来还有“与基数无关的浮点数”的“IEEE 854-1987标准”,有规定基数为2跟10的状况。
根据国际标准 IEEE 754 规定,任意一个浮点数V可表现为此种形式
>> -1^S * M * 2^E (其中-1^S 表示符号位,S为0时,V为正数,S为1时,V为负数;M为有效数字,大于等于1,小于2,2^E指指数位)
举例来讲:5.0的二进制位为 101,相当于1.01*2^2,由此可以得出,S=0,M=1.01,E=2;
-5.0的二进制位为 -101,相当于-1.01*2^2,由此可以得出,S=1,M=1.01,E=2;
IEEE 754 规定:对于一个32位的浮点数,最高的一位为符号位S,接下来的八位为指数位,剩下的二十三位为有效数字位; 对于一个64位的浮点数,最高的一位为符号位S,接下来的十一位为指数位,剩下的五十二位为有效数字位;此外还有一些特别的规定,对与M来讲,计算机內部在保存M时,默认第一位总是1,因此舍去,例如1.001,只存001,等到读取的时候,再把第一位的1给加上,这样做的目的,节省一位有效数字位,以32位机器为例,这样就可以保存24位有效数字了。
至于指数E,情况有些复杂,首先,E为一个无符号整数(unsigned int )这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。
以32位浮点数9.0为例
其二进制位为1001.0,S=0,M=1.001,E=3;
故在内存中的二进制存储格式为
0 10000010 00100000000000000000000
转化为十六进制为
41 10 00 00 00
以小端的形式存储
00 00 00 10 40
然后调试调用内存
在以整形的形式输出的时候,则为
遇上输出结果所对应,而若以整形的形式存储 ,以浮点数的形式输出
0 00000000 00000000000000000001001
以浮点数的形式从内存中取出,其指数位为0,再减去127即-127,2^-127是一个接近于0的数,故在输出的时候为0.000000;