我们都知道数据在内存中是以二进制的形式存储的,但是我们常用的数据有整型、浮点型、字符型,接下来我先介绍整型和浮点型在内存中的存储方式
一、整数的存储
整数的二进制表示方式有三种,分别是原码、反码、补码。
对于有符号整型,原码、反码、补码的第一位是符号位,0表示正,1表示负;而对于无符号整型就没有符号位。此外,在32位环境下的二进制表示方式,第一位是符号位,其余31位是数值位,对于不满31位的二进制数,高位补零;在64位下第一位同样是符号位,其余63位是数值位。对于
原码:将整数转换为二进制之后得到的二进制数字
反码:除了符号位不变,其余位置依次按位取反
补码:反码+1
需要注意的是对于正数和无符号整型而言,其原码、补码、反码相同
以69为例
十进制:69
二进制:01000101
原码: 00000000 00000000 00000000 01000101
反码: 00000000 00000000 00000000 01000101
补码: 00000000 00000000 00000000 01000101
十进制:-69
二进制:- 01000101
原码:10000000 00000000 00000000 01000101
反码:11111111 11111111 11111111 10111010
补码:11111111 11111111 11111111 10111011
给大家看一行代码
int main(int argc, char *argv[]) {
unsigned int i = -69;
printf("%u",i);
return 0;
}
而代码执行的结果是一个非常大的数
这就是因为-69在内存中存储的补码是11111111 11111111 11111111 10111011 ,而将它以无符号整型打印出来时将它的符号位视为数值位,因此打印时由于补码、反码、原码相同,结果就是一个非常大的数。
二、大小端的存储模式
对于超过一个字节的数据在存储时都有存储顺序问题,以一个十六进制的0x11223344的整型为例,整型有四个字节的空间,一个字节有8个比特位,也就是8个二进制位,换算过来就是两个十六进制位,那么0x11223344在内存中是11 22 33 44的方式存储还是以44 33 22 11 方式存储呢。从这就引申出来大小端的概念。
⼤端(存储)模式:是指数据的低位字节内容保存在内存的⾼地址处,⽽数据的⾼位字节内容,保存 在内存的低地址处。
⼩端(存储)模式:是指数据的低位字节内容保存在内存的低地址处,⽽数据的⾼位字节内容,保存 在内存的⾼地址处。
比如上面的0x11223344,小段存储就是 44 33 22 11,大端存储就是11 22 33 44
而小端的优点就是内存的低地址存放数据低字节,大数强制转换小数时效率高,直接丢弃高地址数据即可;cpu在做数值运算时依次从低到高取数运算即可,效率高效。
大端优点:符号位在所表示数据内存的第一个字节,便于快速判断数据的正负和大小。
三、浮点数的存储
根据国际标准IEEE(电⽓和电⼦⼯程协会) 754,对于任意的浮点数V,可以表示成下面的形式
表示符号位,当S=0,V为正数;当S=1,V为负数
M表示有效数字,
表示指数位
以十进制的5.0为例,二进制就是 101.0 ,相当于 (-1)^0 * 1.01 * 2^2,对应的S=0,M=1.01,E=2
IEEE规定,对于32位的浮点数,最高位存储符号位S,接着8位存储指数E,剩下的23位存储有效数字M。
对于64位浮点数,最高位存储符号位S,接着11位存储指数位E,剩下的52位存储有效数字位M
注意事项:
- 因为1<= M < 2,所以M可以写成 1.XXXXX 的形式。IEEE规定,在计算机内部保存M时,默认这个数的第⼀位总是1,因此可以被舍去,只保存后⾯的 XXXXX 部分。
E是无符号整数,它的取值范围为 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。
浮点数取得过程
E不全为0或不全为1
这时浮点数就采用下面的规则表示,即指数E的计算值减去127/1023,得到真实值,再将数字M前加1。
⽐如:0.5 的⼆进制形式为0.1,由于规定正数部分必须为1,即将⼩数点右移1位,则1.0*2^(-1),其 阶码为-1+127(中间值)=126,表⽰为01111110,⽽尾数1.0去掉整数部分为0,补⻬0到23位 00000000000000000000000,则其⼆进制表⽰形式为:
0 01111110 00000000000000000000000
E全为0
这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第⼀位的1,⽽是还 原为0.xxxxxx的⼩数。这样做是为了表⽰±0,以及接近于0的很⼩的数字。
0 00000000 00100000000000000000000
E全为1
这时,如果有效数字M全为0,表⽰±⽆穷⼤(正负取决于符号位s)
0 11111111 00010000000000000000000