前言:相信很多初入编程的小伙伴都有个疑问,到底在创建数据时,在内存中这些数据都是怎样存储的呢,今天带大家了解这个过程
目录
1.整形数据在内存中的存储
1.1.原、反,补码
1.2.大小端
2.浮点型数据在内存在的存储
2.1.浮点数的存储
2.2.浮点数的取出
介绍存储方式前先介绍下计算机中的数据类型
基本内置类型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 表示空类型(无类型)
通常应用于函数的返回类型、函数的参数、指针类型。
这些数据类型就决定了创建的变量所开辟的空间的大小
了解了数据类型,我们接下来看数据在内存在时如何存储的
在计算机底层中存在二进制数,和我们日常所用十进制(计算时逢十进一)数一样,二进制数(逢二进一)即只能用0和1表示,而整数在内存中也就是用二进制数来存储,表示方法:原码,反码,补码三种形式
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位
三种表示方法各不相同。
原码:直接将二进制按照正负数的形式翻译成二进制就可以。
反码:将原码的符号位不变,其他位依次按位取反就可以得到了。
补码:反码+1,正数的原、反、补码都相同。
如下图:
对于整形来说,在内存中一般是以补码形式存储
那为什么呢?
原因在于:使用补码,可以将符号位和数值域统一处理; 同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
下面举个例子说明:
这里内存是以二进制形式存储,只不过在VS编译器上,为方便观察,内存窗口是以十六进制表示
如图3可以看到,整形在内存中不是按原码存储,而是按补码存储
从这个图来看,由于只有加法器,所以必定要和负数进行运算,而用原码来算明显是错误的,而用补码计算还能处理符号位
而在上图3中可以看到,我们计算的十六进制数跟内存中的数是反过来的,这就是大小端存储的问题了
什么是大小端
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位 , ,保存在内存的高地址中。
为什么会存在大小端的分别
计算机事宜字节为单位处理数据,由于一个字节是8个bit,而数据类型在一般情况下(看编译器)占用字节最小char需要一个字节8个bit,int short long 分别占32,16,32个bit,而对于大于8位的处理器,由于寄存器宽度大于一个字节,那就必然存在将多个字节如何安排的问题,就出现了大小端存储,注意,大小端是以字节来说的,所以char型是没有大小端一说的,因为他只有一个字节。
那么如何看你所在的编译器是大端还是小端存储模式呢?
从内存上来看,在VS2019上就是小端存储
小伙伴们可以看看你的编译器是大端还是小端存储,也可以编写代码试试
通过用将int类型的数据强制类型转化成char后,观察返回值也可以判断
先来看一段代码
第一个部分,a里存放的是整形数值 4 ,当以整形形式取出时,正常;但当以浮点数形式取出时异常;
第二部分,通过*p存储浮点数 6.0 ,当以整形形式取出时,异常;但当以浮点数形式取出时正常;
由此说明,浮点数在内存中和整形时不同的,并且,不论哪种类型的数据,以该类型存入内存,就得以该类型取出。
根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数可以表示成下面的形式:
- 》 (-1)^S * M * 2^E
- 》 (-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
- 》 M表示有效数字,大于等于1,小于2。
- 》 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。
明显可以看出,双精度的M比单精度的M大很多,这也是双精度精度更高的原因
其中:对有效数字M和指数E,还有一些特别规定。
对于M,前面说到大于1小于2,所以他总是1,计算机在存储时会舍弃这个1,只保留小数部分,因此M的存储位数就会增加一位,数据能更加精确,在读取的时候再加上1,就能还原数据
对于E,由于E为无符号整形,在使用时又要可存在负数,所以,单精度(E8bit)需要加上中间数127;双精度(11bit)需要加上中间数1023
例如:2^10,在存储时,10+127=137,二进制:10001001
分为三种情况:
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);
好了,先分享到这里,后面有新东西再补充,作为首篇文章,希望能帮到各位,有问题的地方也可与我交流,谢谢!