目录
目前学习到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比特位的在后面全补0,9.0 = (-1)^0 * (1.001)*2^(3),在计算机上的存储为:
第三个printf 打印的就是此时的32比特的二进制位,按整数的方法计算,就是1091567616。
4.第四个printf打印的是存储的9.0,这时打印的就是9.000000.
总结
无符号整数的存储比较简单,这里只列举了有符号整数存储的情况。对于浮点数的存储,计算机无法准确的计算得到比较复杂的小数,比如3.14,3.33这种,只能无限接近,上面列举的都是简单的小数存储的列子,最后,希望各位大佬多多提出宝贵意见,再次谢谢各位。
标签:存储,反码,--,浮点数,补码,整数,C语言,原码 From: https://blog.csdn.net/2301_80966914/article/details/142290696