C语言:整数和浮点数在内存中的存储--(超好理解)

目录

一、整数在内存中的存储(有符号整数)

1.设置反码和补码的的目的

二、浮点数在内存中的存储

1.浮点数取的过程

2.例题解析

总结


目前学习到C语言的各种数据类型在内存中的存储的方式和过程,自己初学的时候下了很多时间去学习理解,为了帮助和自己一样的在第一次初学C语言存储有困惑的小伙伴,本人梳理自己学习过程中的思路和自己的见解,希望对各位有所帮助,共同进步。也希望各位大佬对本文章提出问题,我会及时回复更新文章,谢谢!

一、整数在内存中的存储(有符号整数)

在存储有符号整数的时候,存储的是整数的2进制,整数在转换成2进制存储的时候会有三种形式原码、反码、补码。然而,整数中正数的存储和负数的存储又有一些差异。

正数:原码、反码、补码都相同。

负数:三种表示方法各不相同。

1.解释一下原码、反码、补码是怎末来的。

 1).其实简单来说,原码是我们通过将整数通过变换成2进制直接得到的;

 2).对于负数才有反码补码的概念,所以反码和补码时为了存储负数而单独设置的。

1.设置反码补码的的目的

在上述的图种可以清楚的看出,原码-1在真实值中是加上1,例如:-1的原码 -1 = -0的原码这和我们的习惯上的加减正好相反。所以我们引入了反码,可以有效的解决计算机上存储的2进制加减的问题,例如:-1的反码 -1 = -2的反码。但是,反码的0有两种表现形式,第一种是11111111,第二种是00000000-0的反码加1=0的反码,这就会在负数加正数的时候出现和大于-0的情况,这时候真实值会少1,正是因为0算了两次导致真实值少了1,为了解决负数加正数时出现大于-0的情况下的问题,我们引入了补码,补码的出现,正好解决了两个0的问题,而且空出的一个位置给了-128,规定-128没有原码和反码,只有补码,补码是,10000000


二、浮点数在内存中的存储

 按上面的V的格式,可以得出,S=0 , M=1.01 , E=2 .

 

 对于浮点数的指数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.

1.浮点数取的过程

E从内存中取出来还可以分成三种情况:

1)E不全位0或者不全为1

这时,浮点数采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1.例如:0.5的二进制形式为0.1,由于规定正数部分必须为1,即将小数点右移1位,则为1.0*2^(-1),其阶段码位-1+127(中间值)=126,这时,S=0,M=1.0,E=-1,E的阶段码位126 ,以2进制存储在计算机上表示时,是:

2)E全为0

这时,浮点数的指数E等于1-127(或1-1023),即为真实值,有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示正负0,以及接近于0的很小的数字。

3)E全为1

2.例题解析

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
int main()
{
	int n = 9;
	//n的2进制存储:0000 0000 0000 0000 0000 0000 0000 1001
	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;
}

上述代码运行的结果。 

1.对于int的类型n , 因为n=9,所以它的原码就是它在计算机中的存储形式。

所以第一个printf打印的就是9.

2.对于float* pFloat = (float*)&n;我们可以看出,首先将int n的首地址强制转换为 float*,然后给 同为float**pFloat管理,因为float和int一样都是存储4个字节,所以int类型的32个比特位被以float的存储关系分成了S、E、M三个部分,S存储一个比特的符号位E存储8个比特的指数位M存储23个比特的有效数字。此时,据下图分析,E全为0,E的阶段码位1-127,所以按照上述的E全为0的计算方法:

V = (-1)^0 * 0.00000000000000000001001*2(-126)。

对于第二个printf,V是个无限接近0的数,计算机打印小数点后6位,就是0.000000 

 3.对于*pFloat = 9.0,会将当前的存储的32个比特位按S、E、M来存储,S=0,M=1.001,E=3,E的阶段码为3+127=130所以E存储的是10000010,此时的存储按E不为全0不为全1的情况,,存储M时存储小数位的二进制就行,所以M存储001不满23比特位的在后面全补09.0 = (-1)^0 * (1.001)*2^(3),在计算机上的存储为:

第三个printf 打印的就是此时的32比特的二进制位,按整数的方法计算,就是1091567616

4.第四个printf打印的是存储的9.0,这时打印的就是9.000000.


总结

无符号整数的存储比较简单,这里只列举了有符号整数存储的情况。对于浮点数的存储,计算机无法准确的计算得到比较复杂的小数,比如3.14,3.33这种,只能无限接近,上面列举的都是简单的小数存储的列子,最后,希望各位大佬多多提出宝贵意见,再次谢谢各位。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值