前言
之前给大家介绍了以下几个基本类型,但是关于该存储结构想必大家应该都比较模糊,今天小编就给大家深度刨析以下不同类型在内存的存储模式。( 由于小编之前已经对数据基本类型已经有了一个基本的介绍,今天小编就不过多解释,对于下文一些问题大家可以直接观看小编之前对数据类型介绍的文章)
1.整型在内存的存储
首先这里要给大家引入原码,反码,补码的概念,以及关于内存的存储和他们之间的关系。 对原码,反码,补码,该仅限于有符号整型(有符号整型在小编对数据类型的讲解有具体的介绍,但是为了大家方便理解,这里我给大家简单说以下,有符号整型在内存中占32个bit,具体是由第一位的符号位(0表示正数,1表示负数)和数值位组成),接下来我给大家统一介绍一下
1.1原码,反码,补码
对于正数,该原码,反码,补码是一致的
负数:
原码:原码就是按一个数的正负直接写出该二进制数
反码:符号位不变,其他位直接按位取反,就是反码
补码:反码+1
在计算机的存储中,存储的是一个数的补码形式,那为什么计算机系统要以补码为存储内容呢?
计算机系统中数值一律用补码来表示和存储,原因在于,1.使用补码,可以将符号位和数值域一同处理
2.加法和减法也可以一同处理(CPU只有加法器),补码和原码相同转换,其运算过程是相同的,不需要额外的硬件电路
对于以上有几个点我给大家说明一下
1.加减法一同处理:
这里我给大家举一个例子:假设 32 - 25,这里的减法我们可以看作32+(-25),将两种形式转化为原码,反码,补码分别可以看作
32:原码:000000000000000000000000000100000
反码: 000000000000000000000000000100000
补码:000000000000000000000000000100000
-25:原码:10000000000000000000000000011001
反码:11111111111111111111111111100110
补码:11111111111111111111111111100111
这里我们可以验证一下,加法思想的正确性,这里我么们可以将该补码相加,得到结果的补码是: 00000000 00000000 00000000 00000111
该输出原码是: 00000000 00000000 00000000 00000111,答案换算为十进制为7。
2.补码和原码相同转换,其运算过程是相同的
这里就需要我给大家介绍一下原码和补码的转换关系了,一共有两种转换方法
法一:补码-1,取反
法二:补码取反+1
第一种是定义法,相信大家都能理解,对于第二种方法,这里我继续引用之前-25的例子
这里对-25的补码取反得到的结果是:110000000000000000000000000011000
再对其进行加1操作,大家可以明显的看到该得到的原码是:1000000000000000000000000001100,由于这种转换方式才会导致补码和原码相同转换。
既然大家都明白了,整型在内存中的存储方式,但对于该在内存的存储数据的规则,相信大家
应该不是很理解,这里请跟着小编的步伐继续往下看。
1.2 大端字节序存储和小端字节序存储
这里先引入概念。
大端(大端字节序存储):是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中
小端(小端字节序存储):是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中
知道该概念后这里就需要给大家具体演示了
int main() { int a = 0x11223344; printf("%x\n", a); return 0; }
在vs2019中打开内存,我们可以清楚的看到,以16进制存储的a的内容是将数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中。而这就是小端存储。对于大端字节序存储,达到的就是和该相反的效果。
这里还有段程序可以判断大端字节序和小端字节序的方式的代码,对于这段代码的讲解我们留到讲解指针变量时给大家讲解
int main() { int b = 1; char* q = (char*)&b; if (*q == 1) { printf("小端"); } else { printf("大端"); } return 0; }
2.浮点型在内存的存储
浮点型和整型的存储规则不同,浮点型的存储规则如下:
任何一个二进制浮点数可以表示以下的形式:(-1)^S*M*2^E
-1^S表示符号位,当S=0,V为正数,当S=1,V为负数
M表示有效数字,大于等于1小于2
2^E表示位数
例如:5.5可以表示为(-1)^0*1.011*2^2
对于浮点型的存储,IEEE 754规定:
对于32位的浮点数(即单精度浮点数float),最高一位是符号位S,接着八位是指数E,剩下23位为有效数字M
如图:
对于64位浮点数(即双精度浮点数double),最高位的一位是符号位,接着11位是指数E,剩下52位为有效数字M
如图:
对于以上的存储要求,还有些细节需要大家注意一下
对于M的存储,由于M的范围是1<=M<2,所以在保存的时候,M的整数部分可以省略,读取的时候再加上即可,这样就可以节省一位有效数组,将第一位1省去后就可以保存24位有效数字
对于E:首先E是一个无符号整数,所以如果E为8位,它的取值范围就是0~255,如果E为11位,他的取值范围就是0~2047,但是由于E是可以为负数的所以IEEE 745规定,存入内存时E的真实值必须加上一个中间数,对于8位的E,中间数为127,对于11位的E中间数是1023。
然后指数E从内存中取出的时候还分3种情况
E不全为0或者不全为1,这时浮点数就采用下面规则表示,即指数E的计算值减去127(或者1023),得到真实值,再将有效数组M前加上一位1
E为全0,这时,浮点数的指数E等于1~127(或者1~1023)即为真实值,有效数字M不再加上第一位的1,而是还原为0.几的小数这样做是为了表示+-0,以及无限接近于0的小数
E为全1,表示无穷大的数字,此时就取决于S决定该是正无穷或者是负无穷。