第十八章(数据在内存中的储存)

1. 整数在内存中的存储

2. ⼤⼩端字节序和字节序判断

3. 浮点数在内存中的存储

          我本将心向明月,奈何明月照沟渠

正文开始

一、.整数在内存中的储存

整数的2进制的表示方法有三种
1.原码
2.反码
3.补码

这里在第十章我们有详细讲解,有需要的同学可以自行观看。

二、大小端字节序和字节序判断

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

在这里插入图片描述
2.1 什么是大小端字节序储存呢?

我们来用图形来表示一下

在这里插入图片描述
小端字节序: 是数据的低字节内容保存在低地址处数据的高字节内容保存在高地址处

大端字节序:是数据的低字节内容保存在高地址处
数据的高字节内容保存在低地址处

int check_system(void)
{
	int i = 1;
	return (*(char*)&i);  // 这里我们来强制类型转换是为了判断它的起始收字符是不是为1
		//,如果是1就是小端,否则就大端
}
int main()
{
	int ret = check_system();
	if (1 == ret)
	{
		printf("小端");
	}
	else
	{
		printf("大端");

	}
	return 0;
}

我们该计算机系统用的是小端字节序

三、浮点数在内存中的存储
常见的浮点数:3.14159 、1E10 等,浮点数的家族包括 float,double,long double 类型

这里我们先引入一个练习

#include <stdio.h>
int main()
{
	int n = 9;
	float* pFloat = (float*)&n;
	printf("n的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);
	*pFloat = 9.0;
	printf("num的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);
	return 0;
}

在这里插入图片描述
3.2 浮点数的存储

通过上面我们可以看出,n 和*pFloat 在明明是一个数,为什么浮点数和整数的解读结果会差别很大呢?

我们可以猜测一下,难道是因为浮点数和整数的储存方式是不一样的吗?
接下来我们来分析浮点数在内存中的储存方式

根据国际标准IEEE(电⽓和电⼦⼯程协会) 754,任意⼀个⼆进制浮点数V可以表⽰成下⾯的形式:
V = (−1) ∗ S M ∗ 在这里插入图片描述

• (−1)S 表⽰符号位,当S=0,V为正数;当S=1,V为负数
• M 表⽰有效数字,M是⼤于等于1,⼩于2的
在这里插入图片描述
表示的是指数位

举例来说:十进制的5.0,写成二进制是101.0,相当于1.01 * 2^2
那么我们按照上边的关系就可以得出

  1. S = 0
  2. M=1.01
  3. E = 2

IEEE规定:
对于32位的浮点数,最高的1位储存符号位 S ,接着8位储存指数E,剩下的32位储存有效数字M

对于64位的浮点数,最高的1位储存符号位 S ,接着11位储存指数E,剩下的52位储存有效数字M
在这里插入图片描述
3.2.1 浮点数储存的一些特点
对于有效数字M和指数E
还有一些特殊的规定:
1.
前⾯说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中 xxxxxx 表⽰⼩数部分。在计算机内部保存M时,默认这个数的第⼀位总是1,因此可以被舍去,只保存后⾯的xxxxxx部分。⽐如保存1.01的时候,只保存01,等到读取的时候,再把第⼀位的1加上去。这样做的⽬的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第⼀位的1舍去以后,等于可以保存24位有效数字。

首先我们要知道的是E为一个无符号整数
但是科学计数法E是可以出现负数的,所以规定就说
存⼊内存时E的真实值必须再加上⼀个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数1023。⽐如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。

3.2.2
浮点数取得过程
指数E从内存中取出还可以分为以下三种情况

1.E不全为0或不全为1(正常取)
这时,浮点数就采⽤下⾯的规则表⽰,即指数E的计算值减去127(或1023),得到真实值,再将有效
数字M前加上第⼀位的1。
在这里插入图片描述

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

在这里插入图片描述

3.E全为1
这时,如果有效数字M全为0,表⽰±⽆穷⼤(正负取决于符号位s);
在这里插入图片描述
这里我们就可以重新的分析上边的那个例子

#include <stdio.h>
int main()
{
	int n = 9;
	//9的正数原码反码补码都是
	//00000000000000000000000000001001
	float* pFloat = (float*)&n;
	//0 00000000 00000000000000000001001
	
	printf("n的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);
	// S = 0 ,E = 1-127 , M = 00000000000000000001001
	// V = (-1)^0 × 0.00000000000000000001001×2^(-126)=1.001×2^(-146) 约等于0


	*pFloat = 9.0;
	//9.0的二进制为1001.0 = 1.001 * 2^3
	//9.0在内存中的储存为
	//0 10000010 0010000000000000000000
	printf("num的值为:%d\n", n);
	// 按照 十进制的读取方式就为
	//0100000100010000000000000000000  ==1091567616
    //0 为正整数原码反码补码相同
	printf("*pFloat的值为:%f\n", *pFloat);
	//0 10000010 0010000000000000000000
	//我们还原 就可得到
	//S = 0
	//M = 1.001
	//E = 130-127 = 3
	//V = (-1)^0 * 1.001 * 2^3
	return 0;
}

总结:
我们在内存中如果以整数储存数据,但是用浮点数的方式来读取,用的是浮点数的读取规则。

我们在内存中如果以浮点数储存数据,但是用整数的方式来读取,用的是整数的读取规则。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值