C语言深度剖析数据在内存中的存储

数据类型介绍

整形家族:有符号和无符号

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 //双精度浮点型

构造类型:

数组类型
结构体类型 struct
枚举类型 enum
联合类型 union

指针类型 空类型:

void 表示是空类型
常用语函数返回值类型、函数参数、指针类型

上面将来这些常用的数据类型,但是这些数据类型有什么用处呢?
数据类型的意义:

  1. 使用对应类型决定了开辟空间的大小
  2. 如何看待内存空间的视角

整形在内存中的存储

我们可以知道,声明创建一个变量就要在内存中为其开辟空间,变量的类型决定了开辟多大空间。但是对变量中的数据在内存空间是如何存储的却不知道?

先来说一下:原码、反码、补码
计算机中有符号数有三种表示方法,即原码、反码、补码,这三种方法均有符号位和数值位两个部分,符号位正负用0/1表示,而数值为三种方法各不相同。

原码:直接将数按照二进制正负数的形式翻译成为二进制就是原码;
反码:就是将原码符号位不变,数值位一次按位取反,就是反码
补码:给反码 +1就是补码,
注意:正数的原码、反码、补码都是相同的;

对于整形来说:数据在内存中都是以补码的形式进行存储的;

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

C语言深度剖析数据在内存中的存储_第1张图片我们根据a和b存储的补码,和我们转换过的补码顺序有点不一样?这里就要就要引出大小端
大小端(存储)介绍:

大端存储模式:指的是将数据的地位存储在内存的高地址中,将数据的高位存储在内存的低地址中;
大端存储模式:指的是将数据的地位存储在内存的低地址中,将数据的高位存储在内存的高地址中;

关于详细的大小端请在我另外一篇博客中查看大小端(存储)模式辨析

浮点型在内存中的存储

根据国际标准,任意一个二进制浮点数都可表示成下面的形式:

(-1)^S * M * 2^E
(-1)^S 表示符号位,s = 0 为正 s = 1为负
M表示有效数字,大于1小于2
2^E表示指数位
举栗子1: 十进制5.0,写成二进制101.0,相当于1.01x2^2。可退出S = 0, M = 1.01,E=2
举栗子2: 十进制-5.0,写成二进制-101.0,相当于-1.01x2^2。可退出S = 1, M = 1.01,E=2

IEEE 754规定:对于32位浮点数,最高1位是符号位S,下来是8位指数位E,剩下为23位有效数M。
C语言深度剖析数据在内存中的存储_第2张图片
IEEE 754规定:对于64位浮点数,最高1位是符号位S,下来是11位指数位E,剩下为52位有效数M。
C语言深度剖析数据在内存中的存储_第3张图片
IEEE745其中对有效数字M和指数E,有一些特殊要求
有效数M:1<=M<2,M可以写成1.xxxxxxx。其中xxxxxx表示小数部分;

IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字

指数E: 情况就比较特殊
首先E是一个无符号整数,如果E是8位 其取值范围 0 - 255;如果E是11位 其取值范围0 - 2047.但是我们可知科学计数法中E可能出现负数,所以**IEEE754规定 :存入内存时E的真实值必须加还加上一个中间数,对于8位的E,中间数是127;对于11位的E,中间数1023.**例如:2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001

指数E从内存中取出时可以分为三种情况:
1、E不全为0或不全为1

这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。 比如: 0.5(1/2)的二进制形式为0.1,由于规定正数部分必须为1,即将小数点右移1位,则为1.0*2^(-1),其阶码为-1+127=126,表示为01111110,而尾数1.0去掉整数部分为0,补齐0到23位00000000000000000000000,则其二进制表示形式为0 01111110 00000000000000000000000

2、E全为0

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

3、E全为1

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

C语言深度剖析数据在内存中的存储_第4张图片
1、为什么0x00000009还原成浮点数就成了0.000000?

9的二进制:00000000 00000000 00000000 00001001
拆分成:S = 0, E = 00000000, M = 0000000 00000000 00001001

由于E全为0,此时浮点数V表示为:V = (-1)^0 x 0000000 00000000 00001001 x 2^(-126) 
= 1.001 x 2^(-146)显然很接近0,十进制小数表示就是:0.000000

2、浮点数9.0,如何用二进制表示?还原成十进制又是多少?

浮点数9.0二进制:1001.0,即1.001 x 2^3;S = 0,E = 3+127,M=1.001
所以二进制表示为:0 10000010 001 0000 0000 0000 0000 0000

你可能感兴趣的:(c)