数据在内存中的存储

我们知道在程序运行时,我们的数据通过二进制的形式存储在内存中。但是数据具体是如何存储的呢?我们来进行详细的说明。

首先,不同种类的数据存储方式是不同的,从种类来说,有整形,浮点型,构造类型,指针类型以及空类型,不同的类型决定了他们在内存中占用的空间以及看待内存空间的视角。今天我们在此介绍整形与浮点型的存储。

我们知道,整形分为int,shrot,char,long,long long这么多种类型。我们先从int型入手,看看他在内存中是如何存储的。

int型数据是由32个比特位构成的数据,也就是四个字节。要想知道他是如何在内存中进行储存的,我们先来了解一个概念:原码,反码,补码。

一个有符号数由符号位和数值位组成。而有符号数的最高位(也就是字符位)上的0表示正数,1表示负数,除了最高位其余都是符号位。一个数据的原码只需要按照数值大小和符号翻译成二进制位就可以得到。

但是在计算机中储存的整形数据是以补码的方式进行存储的,补码需要进行以下的操作获得。我们拿-1进行举例。

-1的原码是10000000 00000000 00000000 00000001

反码是将原码除了符号位以外所有位按位取反得到的。

所以-1的反码是11111111 11111111 11111111 11111110

补码是将反码+1得到的。

所以-1的补码就是11111111 11111111 11111111 11111111

而对于正数而言,它的原码,反码,补码都相同。

接着我们打开内存查看来看看一个整形数据在内存中是如何存放的。我们构造一个整形变量a。

int main()
{
    int a = 3;
}

 

 从上面的内存查看中可以观察到,a在内存中存放的数据是03 00 00 00,但是按照补码的方式存储,不应该存储00 00 00 03吗?

其实,在存储上有个大小端存储模式的概念。

大端模式就是指数据的低位保存在内存的高地址中,数据的高位,保存在内存的低地址中。

小端模式就是指数据的低位保存在内存的低地址中,数据的高位,保存在内存的高地址中。

对于一个十六进制数0x11 22 33 44而言,它的大小端存储方式如下

 

 介绍完了整形数据,接下来我们介绍浮点型数据的存储。

这里我们先看一段代码。

#include <stdio.h>
int main()
{	
	int a = 6;
	float* pa = (float*)&a;
	printf("%d\n", a);
	printf("%f\n", *pa);
	*pa = 6.0;
	printf("%d\n", a);
	printf("%f\n", *pa);
	return 0;
}

大家觉得这里的运行结果是什么呢?

结果是下面这样的。

可以看到,虽然数值的具体大小没有改变,但是输出的数据却是截然不同,这是为什么呢?

其实,浮点型和整形数据的储存有很大区别。

一个二进制浮点数V可以表示为:(-1)^S*M*2^E。

(-1)^S表示符号位,当S=0,V为正数,S=1,V为负数。

M表示有效数字,大于等于1,小于2。

2^E表示指数位。

对于32位的浮点数。它的第一位是符号位S,2-9位为指数位E,其余位为有效数字位M。

 

对于64位的浮点数,它的第一位是符号位S,2-12位为指数位E,其余位为有效数字位M。

拿单精度浮点数6.0举例。

它的符号位S=0,表示它是一个正数。

而6用二进制可以表示为110,但是用科学计数法,就成了1.1*(2^2)。就像十进制里,123可以表示为1.23*(10^2)一样。

但是,M里面存的二进制难道是1.1吗?我们知道,对于一个非零二进制数,他的第一位一定是1,所以为了能表示更多的内容,计算机在存储浮点数的时候,会去掉首位上的1,所以对于6.0来说,他的M保存的是小数点后面的1,然后在1后面加上0,直到满23位,就形成了6.0这个float类型数据的有效数字M部分了。而当要表示这个数时,会将去掉的1补回去。

对于它的E,里面存的是2吗?其实也不是。这里的E,其实是一个无符号的整数,所以它的取值范围只有0~255,你可能会说,这不是包括了2吗?但是如果这么想,那么2^-1就无法用E=-1来表示了。所以,我们将8位的E取127为中间值。而11位的E取1023为中间值,这个中间值怎么用呢?比如上面的例子,6的E应该取值为2+127=129,而不是2。若要表示2^-1,那么E的取值就是(-1)+127=126。

所以,6.0以float类型存储时,他的32位二进制数字是

0 10000001 10000000000000000000000

转换为16进制数字为0x40C00000

我们知道目前设备的存储模式为小端存储模式,所以在内存中该数据应该表示为00 00 C0 40

我们打开内存查看6.0以float类型存储的情况以验证我们的说法。 

可以看到该数据确实是以这样的形式存储的。

除了一般的情况,当E全为0时,指数表示为2^(-126) (对于64位浮点数来说,此时指数表示为2^(-1022)),有效位不会将1补回,例如有效位为1.001时,会被直接当成0.001处理。这样做是为了表示十分接近+-0的数字。

而当E全为1时,如果此时有效数字位M全为0,则表示+-无穷大,正负则取决于符号位S。

到这里,整数与浮点数的存储就算是介绍完啦~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值