C语言 浮点型在内存中的存储

一、浮点类型要点

  1. 常见浮点型:float(四字节)、double(八字节)
  2. 浮点类型没有无符号类型,也就是说浮点型内存中一定有符号位
  3. 与浮点型有关的操作不会发生整型提升(只在char与int之类的整型之间),但是要注意隐式类型转换
  4. 浮点型数据不能作 == 或 != 比较,只可区间比较(解释在下文)

二、浮点型储存规律

  1. 通过例子了解浮点型与整型的差异:
int main()
{
    
    
	int n = 9;
	float *pf = (float *)&n;
	printf("第一次n值为:%d\n", n);
	printf("第一次*pf值为:%f\n", *pf);

	*pf = 9.0;
	printf("\n第二次n值为:%d\n", n);
	printf("*第二次pf值为:%f\n", *pf);

	system("pause");
	return 0;
}

在这里插入图片描述

第一次输出 n 的值与解引用 *pf 的值不同,说明了浮点型变量对内存读取数据的方式与整型不同(我的上篇博客详细讲解了数据在内存的存在形式与数据类型的关系);
第二次通过解引用令变量 n 重新赋值 9.0,出现了 int 类型的变量 n 以整数形式输出并不是9的结果,进一步佐证了数据在内存的存在形式与变量的数据类型并无关系

  1. 存储原理
    我们知道,无符号整型 在内存中直接开辟32 bit位存储二进制数据;有符号整型 将32位的第一位作为符号位,剩余的31位存放二进制数据;但是对于浮点型数据 来说,除了符号位外,还有两种二进制数据:一种小数点前的数值,一种小数点后的数值。

    现在计算机采用了国际标准IEEE754,严谨的存储了浮点数据:
    任一个小数可以表示为:(-1)^S * M * 2^E 这种形式

    S 符号位,当s=0,值为正数;当s=1,值为负数;

    M 基数位,对于二进制来说,这个值大于2小于1,那么在存放时,规定省略基数的前半部分(都一样),只存放小数点后的数据

    E 指数位, 在数学概念上,指数位是有正负之分,而内存中指数位区域并未专门设置符号位,而是通过 ±中间数 实现;float类型中指数位有8位,取值范围[0,255],中间数127 操作后的实际范围是[-127,128];double类型中指数位有11位,取值范围[0,2047],中间数1023 操作后的实际范围是[-1023,1024].

  • float类型

    对于float类型,在内存中将四字节32位bit空间如下图多分,一个小数在存到内存时,先转换为二进制数,再将这个数以科学计数法表示,得到该数的正负、基数和指数,并按规则写入内存
    例如十进制的-5.0,写成二进制是 -101.0 ,相当于 -1.01×2^2 。那么,s=1,M=1.01,E=2+127=129
    按float保存后:1 10000001 01000000000000000000000
    在这里插入图片描述

  • double类型
    在这里插入图片描述

  1. 要点4解释(浮点型精度)
    E全为0

    浮点数的指数E等于1-127(或者1-1023)即为真实值, 有效数字M不再加上第一位的1,而是还原为
    0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
    正是由于浮点型数据有这样的特殊性,不能直接比较

    E全为1

    这时,如果有效数字M全为0,表示±无穷个最大值(正负取决于符号位s);

三、例题解释

  1. int 型变量 n 一开始存放的是整型数值 9,也就是说该变量空间内是9的32位二进制:0000…0000 1001

    %d整型形式 输出则按原反补输出,出现第一个结果9;

    %f浮点型形式输出则按指数位,基数位转换输出:指数位全为0,故输出结果为0.

    在这里插入图片描述

  2. int 型变量 n 的空间内容被解引用放入了浮点型9.0的二进制数据:符号位为0,指数位为127+3,基数位为0010…0000 即为:0 10000010 00100000000000000000000

    %d整型形式 输出则按原反补输出,出现第一个结果1,091,567,616;
    在这里插入图片描述

    %f浮点型形式 输出则按指数位,基数位转换输出结果为9.00000.

    在这里插入图片描述

Guess you like

Origin blog.csdn.net/Sober_harmonic/article/details/120679919