数据在内存中的存储——了解存储规则

        前言:相信很多初入编程的小伙伴都有个疑问,到底在创建数据时,在内存中这些数据都是怎样存储的呢,今天带大家了解这个过程


目录

1.整形数据在内存中的存储

        1.1.原、反,补码

        1.2.大小端

2.浮点型数据在内存在的存储

        2.1.浮点数的存储

        2.2.浮点数的取出


1.整形数据在内存中的存储

 介绍存储方式前先介绍下计算机中的数据类型

基本内置类型
char         // 字符数据类型
short       // 短整型
int         // 整形
long         // 长整型
long long   // 更长的整形
float       // 单精度浮点数
double       // 双精度浮点数
整形家族
char        //字符型
unsigned char        //无符号字符型
signed char            //有符号字符型
short        //短整型
unsigned short [ int ]       //无符号短整型
signed short [ int ]           //有符号短整型
int        //整形
unsigned int        //无符号整形
signed int         //有符号整形
long        //长整形
unsigned long [ int ]       //无符号长整形
signed long [ int ]          //有符号长整型

浮点数家族

float      //浮点型

double  //双精度浮点型

构造型

arr[ ]  组类型

 struct   结构体类型

 enum 枚举类型

 union 联合类型

指针类型

int *pi;   整形指针

char *pc;   字符指针

float* pf;    浮点型指针

void* pv;   空类型指针

空类型:

void 表示空类型(无类型)

通常应用于函数的返回类型、函数的参数、指针类型。 


这些数据类型就决定了创建的变量所开辟的空间的大小

了解了数据类型,我们接下来看数据在内存在时如何存储的

 1.1.原、反,补码

在计算机底层中存在二进制数,和我们日常所用十进制(计算时逢十进一)数一样,二进制数(逢二进一)即只能用0和1表示,而整数在内存中也就是用二进制数来存储,表示方法:原码,反码,补码三种形式

三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位

三种表示方法各不相同。

原码:直接将二进制按照正负数的形式翻译成二进制就可以。

反码:将原码的符号位不变,其他位依次按位取反就可以得到了。

补码:反码+1,正数的原、反、补码都相同。

如下图:

对于整形来说,在内存中一般是以补码形式存储

那为什么呢?

原因在于:使用补码,可以将符号位和数值域统一处理; 同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

下面举个例子说明:

这里内存是以二进制形式存储,只不过在VS编译器上,为方便观察,内存窗口是以十六进制表示

如图3可以看到,整形在内存中不是按原码存储,而是按补码存储

从这个图来看,由于只有加法器,所以必定要和负数进行运算,而用原码来算明显是错误的,而用补码计算还能处理符号位

而在上图3中可以看到,我们计算的十六进制数跟内存中的数是反过来的,这就是大小端存储的问题了


1.2.大小端

什么是大小端

大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位 , ,保存在内存的高地址中。

为什么会存在大小端的分别

计算机事宜字节为单位处理数据,由于一个字节是8个bit,而数据类型在一般情况下(看编译器)占用字节最小char需要一个字节8个bit,int  short  long 分别占32,16,32个bit,而对于大于8位的处理器,由于寄存器宽度大于一个字节,那就必然存在将多个字节如何安排的问题,就出现了大小端存储,注意,大小端是以字节来说的,所以char型是没有大小端一说的,因为他只有一个字节。

那么如何看你所在的编译器是大端还是小端存储模式呢?

从内存上来看,在VS2019上就是小端存储

小伙伴们可以看看你的编译器是大端还是小端存储,也可以编写代码试试

通过用将int类型的数据强制类型转化成char后,观察返回值也可以判断

2.浮点型数据在内存在的存储

先来看一段代码

第一个部分,a里存放的是整形数值 4 ,当以整形形式取出时,正常;但当以浮点数形式取出时异常;

第二部分,通过*p存储浮点数 6.0 ,当以整形形式取出时,异常;但当以浮点数形式取出时正常;

由此说明,浮点数在内存中和整形时不同的,并且,不论哪种类型的数据,以该类型存入内存,就得以该类型取出。

2.1.浮点数的存储

根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数可以表示成下面的形式:

  •              》 (-1)^S * M * 2^E
  •              》 (-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
  •              》 M表示有效数字,大于等于1,小于2。
  •              》 2^E表示指数位。
    •  
      •                                            V = (-1)^S*M*2^E

浮点数4.5的二进制表示:整数部分:100;小数部分:1

所以4.5的浮点数表示为:1*1.001*2^2

这里 s = 0;M= 1.001;E = 2

浮点数4.5的二进制表示:整数部分:-100;小数部分:1

所以4.5的浮点数表示为:-1.001*2^2

 这里 s = 1;M= 1.001;E = 2                              ​​​

那究竟浮点数在内存中是怎么存储的呢?

IEEE 754规定:1.对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。

                          2.对于64位的浮点数,最高的1 位是符号位s ,接着的 11 位是指数 E ,剩下的 52 位为有效数字 M

明显可以看出,双精度的M比单精度的M大很多,这也是双精度精度更高的原因

其中:对有效数字M和指数E,还有一些特别规定。

对于M,前面说到大于1小于2,所以他总是1,计算机在存储时会舍弃这个1,只保留小数部分,因此M的存储位数就会增加一位,数据能更加精确,在读取的时候再加上1,就能还原数据

对于E,由于E为无符号整形,在使用时又要可存在负数,所以,单精度(E8bit)需要加上中间数127;双精度(11bit)需要加上中间数1023

例如:2^10,在存储时,10+127=137,二进制:10001001

2.2.浮点数的取出

分为三种情况:

E不全为0或不全为1:指数E的计算值减去127(或1023),得到真实值,再将有效数字M前

加上第一位的1。

E全为0:指数E等于1-127(或者1-1023)即为真实值, 有效数字M不再加上第一位的1,而是还原为 0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。

E全为1:如果有效数字M全为0,表示±无穷大(正负取决于符号位s);

        好了,先分享到这里,后面有新东西再补充,作为首篇文章,希望能帮到各位,有问题的地方也可与我交流,谢谢!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值