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

在深度剖析之前,先大致介绍一下各数据类型

首先数据类型的意义是使用这个类型去开辟内存空间的大小

而类型的基本归类分别是

整形家族 :

char    short    int    long    long long

tip:(将char分为整形的理由是因其存的ASCII码值的本质为整数,故将其分类为整形家族)

浮点型家族:

double    float

构造类型(自定义类型) :

数组类型  结构体类型  枚举类型  联合类型

指针类型: 

int*    char*    float*    void*

空类型(通常应用于函数的返回类型函数的参数指针类型) :

void test()      void test(void)     void* p


接下来要介绍的才是正戏

数据在内存中的存储 :

1. 整形在内存中的存储   

                              

2. 浮点型在内存中的存储

 在这里我们先说整形在内存中的存储


1.整形在内存中的存储  

 首先我们知道,整形在内存中存放的其实是补码

(简单介绍一下原码、反码和补码)
 int a = -10;
//10000000000000000000000000001010--原码
//11111111111111111111111111110101--反码
//11111111111111111111111111110110--补码
//想求一原码的补码只需对原码:按位取反再+1即可
int a = 10;
//00000000000000000000000000001010--原码=反码=补码(正数的3码相同)
接下来引入一个重要概念:

大端字节序存储和小端字节序存储

(一般称为:大端小端

 所谓的大端就是指将数据的高位字节保存在内存的低地址中,而将数据的低位字节保存在内存的高地址中(小端的话则相反,高存高,低存低)

单说文字可能有些抽象,这里我直接上代码大家就能明白怎么个事了: 

代码如下:

int main()
{
		int a = 0x11223344;
		return 0;
}

这时候我们在打开内存查看a的地址(&a),能看到:

 我们会发现数据并不是11 22  33 44这样子存储,相反的,是反过来存储

我们再来看看地址的高低变化:

不难看出,地址是从低到高的顺序安排的

而我们通过观察能得出a数据里面的44属于数据的低位字节它存放在地址中的低地址

11属于数据的高位字节它存放在地址中的高地址

因此我们可以知道该编译器的存储方式是小端存储(该版是VS2019)

通过清晰的代码调试分析,我们就可以较为轻松的搞明白整形在内存中的存储,如果想知道自己的编译器是哪种存储方式,这里也有一道简单的代码可以用来自测,如下:

//判断当前编译器是大端还是小端
int main()
{
	int a = 0x11223344;
	char* p = (char*)&a;
	if (*(p + 3) == 0x44)
		printf("为大端\n");
	else if (*(p + 3) == 0x11)
		printf("为小端\n");
	printf("%d   %x", *(p + 3),*(p+3));
	return 0;
}

2.浮点型在内存中的存储

 首先要知道,任何一个二进制的浮点数都可以表示为如下公式:

V=(-1)^S * M * 2^E

S:表示符号位,S=0则为正数,S=1则为负数

M:表示有效数字(1<=M<2)

E:表示指数位

 举个例子吧!

V=5.5
->101.1(将5.5转化为二进制)
->1.011 * 2^2(小数点向左移动了两位,E=2)
->(-1)^0 * 1.011 * 2^2(因为是正数,所以S=0)
=>(-1)^s *   M   * 2^E(对应公式) 

通过这个代码能够更直观的理解该条公式如何应用

现在公式讲完了,那么回到标题:浮点型是如何存在数据里的呢?

我们以单精度浮点型(float (32位))为例(其中会穿插double(64位)的介绍):

先画出float内存的大致图形:

 先介绍S(符号位):

S的存放很简单,如果为正数便存0,如果为负数便存1

M:

存放M时,要将整数部分的去掉,这样子就可以多拿一个bit位来存放数值

以上面的代码为例,我们的M为1.011,那么就将整数1去掉,存入011,后面读取时再将1放回即可

tip:double(64位)中M有53个bit位

E:(最复杂的) 

有三种情况,如下:

1.E不全为0或不全为1

  因为E是一个无符号的数,但是存的值是有正负的,因此我们需要加上一个中间值:127

(double(64位)则需加上1023)

仍然以上面的代码为例,E=2,那么就可以算作 2+127 = 129 其对应的二进制位是10000001

2.E全为0

此时E=1-127即为真实值(需要注意M不再加上第一位,而是0.xxxxx的形式,因为此时已经无限接近于0了

3.E全为1

这时如果M全为0,则表示±无穷大

tip:double(64位)中E有11个bit位

 说了那么多,现在我们来看看float类型里的5.5时如何存储的吧:

0   10000001   01100000000000000000000

 再合并一下就是:

01000000101100000000000000000000

 所以float类型里的5.5在内存中的存储就是如此


到此深度剖析数据在内存中的存储就结束了,希望我的文章能对博友有所帮助

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值