数据在内存中的储存

一.整型数据

整数用二进制表达有三种方式:原码,反码,补码。三种表示方式均由符号位和数值位组成,符号位上数字1表示负数,数字0表示正数。在有符号整型中,最高位表示符号位,剩余表示数值位。无符号整型则都视为数值位。

对于正数而言,它的原码反码补码都相同,对于负数而言,三种形式各不相同需要转换。

原码:直接将数字转化为二进制得到的就是原码。(正负数是符号位的不同)

反码:符号位不变,数值位全部取反。(0变1,1变0)

补码:在反码的基础上+1得到补码。

通过以上的转化方法,可以总结为:原码转补码,取反+1。这个方法不仅适用于原码转补码,也适用与补码转原码,巧妙之处就在于仅需一个相同步骤便能实现互相转换。

整形数据存储在内存中以补码的形式。原因是CPU只有加法处理器,统一为补码便能将减法转化为加法,如2-1转化为2+(-1),将加减法统一,并且补码原码相互转换只需一个相同步骤(取反+1),这样就不需要额外的硬件电路。

二.大小端字节序判断

数据存储在内存中存在顺序问题,内存排布有地址高低顺序,那么存储数据是按着何种方式?这里分为两种不同的类型:大端字节序与小端字节序。

大端字节序储存:是指数据的低位字节内容保存在内存的高地址处,而数据的高位字节内容,保存在内存的低地址处。

小端字节序储存:是指数据的低位字节内容保存在内存的低地址处,而数据的高位字节内容,保存在内存的高地址处。

什么是低位字节内容?举个简单的例子:123,其中3就是低位字节内容,在大端中3-2-1地址由高到低,而小端则是地址由低到高。下图展现了存储0x11223344时大小端的不同。

当然我们也可以在编译器中从内存窗口里查看该系统是大端还是小端。下图就是在VS的内存窗口中查看的,可见,这是小端的标志。

除了调试外,我们也能自己写个程序来判断机器是大端还是小端,如下便可实现。

int check(int a)
{
	return  *((char*)&a);//强转char*便于访问一个字节的内容
}

int main()
{
    // 1对应 00 00 00 01如果返回为1证明是小端储存
	printf("%d ", check(1));

	return 0;
}

三.浮点型数据

像float,double等浮点型数据,与整型数据的储存格式是不一样的。转化二进制浮点数需要参考以下标准

 举例来说,如5.5,可以写成101.1,也就是1.011×2^2,那么转化为以上形式,S=0,E=2,M=1.011.既然将一个浮点数拆分为了三部分,那么这三部分如何在内存中储存呢?就以float为例:

如此,一个4字节大小(32bit)的数据就这样被储存在内存中,这与整型直接存储补码的形式大相径庭。如果是双精度浮点型,如double,那么就是S(1bit),E(11bit),M(52bit)进行储存了。 

但是IEEE 754 对有效数字M和指数E,还有⼀些特别规定。

对于有效数字M而言,M是大于等于1小于2的,那么所有M都可以省略最前的1,这样就能节省一位有效数字,例如前文的M=1.011那么存储时M区只需要存储011就行了。

对于指数E而言,E是一个无符号数(unsigned int),但是众所周知,指数是可以取负的,所以IEEE 754就规定了一个中间数,若E为8位,那么取值范围就为0~255,中间数就是127,存入内存时E的真实值就要加上这个中间数,这样就能存储负的指数了。例如E真实值为10时,就要加上127等于137再进行存储。如果是11位的E,那么中间数就是1023。

特殊情况,当E全为0时,真实值就等于1-127(或者1-1023)而不是0-127。有效数字M不再加上第⼀位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小很小的数字。而当E全为1时,这时,如果有效数字M全为0,表示±无穷大。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值