一、整形在内存中的存储
1.1 原码、反码、补码
计算机中的整数有三中2进制表示方法,即原码、反码、补码。
三中表示方法都有符号位、和数值位两部分,符号位用0表示正,用1表示负。
对于整数来说内存中存放的是其对应的补码。这是因为使用补码,可以将符号位和数值与同一处理。
同时,加法和减法也可以统一处理(CPU只有加法器)。
原码:将数值按照正负数的形式翻译成二进制,就是其原码。
反码:原码的符号位不变,其他位依次取反就是反码。
补码:反码+1就是补码。
注意:正整数的原码、反码、补码都相同。
1.2大小端字节序存储
什么是大端、小端存储模式?
大端存储模式:数据的低位保存在内存的高地址中,数据的高位保存在内存的低地址中。
小端存储模式:数据的低位保存在内存的低地址中,数据的高位保存在内存的高地址中。
如图是小端存储:
为什么会有大端小端之分呢?
在计算机中是以字节为单位的,每个地址单元都对应1个字节,但有的数据类型并不是1个字节,那么如何安排多个字节数据中各字节存放顺序问题,所以就有了大小端字节序存储。
如何查看当前是按大端存储还是小端呢?
int main()
{
int n1 = 0x00000001;
//如果是小端的话,那么存储:
//低地址 高地址
//0x 01 00 00 00 //16进制写法
//所以只要知道第一个字节是否为1
char* pn = (char*)&n1;
if (*pn == 1)
{
printf("小端存储~");
}
else
{
printf("大端存储~");
}
return 0;
}
二、浮点型在内存中的存储
2.1浮点数存储规则
根据国际标准IEEE754,任意一个二进制浮点数可以表示下面形式:
(-1)^S * M * 2^E
(-1)^S 表示符号位,S=0,表示正,S=1,表示负
M表示有效数字,大于等于1,小于2
2^E表示指数位
举个例子:十进制5.5 -> 二进制:101.1
S=0
M=1.011
E=2+ 127/1023(下面说明为什么要+127/1023)
IEEE 754规定:
对于32位的浮点数,最高的1位是符号位S,接着的8位是指数E,剩下的23位为有效数字M。
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。
2.2对于浮点数中的M
IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的
xxxxxx部分。等到读取的时候,再把第一位的1加上去。
2.3对于浮点数中的E
E是一个无符号整数,当时科学技术法中E可以为负数,所以IEEE754规定,存入内存是E的真实值必须再加上一个中间数,对于float,即8位E,这个中间数是127。对于double,即11位E,这个中间数是1023。
所以5.5是这样存储的:
2.4浮点数读取
1)E不全为0或不全为1:
E的计算值减去127/1023, 得到真实值,再讲有效数字M前加上第一位1.
如:5.5f 内存中的存储形式:
0 100000001 01100000000000000000000
读取时:
E = 129 - 127 = 2
M = .011 + 1.0 = 1.011
S = 0
所以5.5f的二进制从内存中读取出来:
(-1)^0 * 1.011 * 2 ^2 = 101.1, 也就是十进制的5.5
2)E全为0:
由于在内存中存储的时候是加上了127/1023的,但现在存储的却都是0,说明真实值为-127/-1023,这个数要乘以 2^-127次方,等到一个无限接近于0的数。所以此时有效数字M不再加上第一位的1,而是还原0.xxxxx的小数。
3)E全为1:
同理E的真实值为128,指数位很大,说明这个数无穷大。