深度刨析数据在内存中的存储,打通你的任督二脉

数据类型的介绍

char
short
int
long
long long
float
double

类型的基本归类

整型家族

char

unsigned char
signed char

short

unsigned short
signed short

int

unsigned int
signed int

long

unsigned long
signed long

long long

unsigned long long
signed long long

char在整型家族因为在内存中存放的是它的ascll码

浮点家族

float
double

构造类型

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

指针类型

int* pi
char* pc
float* pf
void* pv

void表示空类型(无类型)
通常应用与函数的返回类型,函数的参数,指针类型

整型在类型中的存储

在前面已经介绍,感兴趣的小伙伴可以去看看增加内功详细讲解整数如何在内存中存储

大小端介绍

什么是大小端?

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

在这里插入图片描述
为什么会有大小端呢?

因为在计算机系统中,我们以字节为单位,每个地址的单元都对应这一个字节,一个字节是8bie,但是在c语言中除了8bit之外,还有16bit的short,等等,另外,对于位数大于8位的处理器,例如16位或者32的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多字节安排的问题,因此就有了大端存储模式和小端存储模式

接下来测试一下自己的当前的机器的字节序
在这里插入图片描述
在这里插入图片描述
经过调试,我们确实可以看出我们的机器当前使用的就是小端存储模式

测试对前面知识掌握的练习题

先自己思考一下,在测试答案,如果都对,不错你的知识掌握的非常好!可以结合详细讲解整数如何在内存中存储
%d打印有符号整数
%u打印无符号整数

int main()
{
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("%d %d %d\n", a, b, c);
	return 0;

}
int main()
{
	char a = -128;
	printf("%u\n", a);
	return 0;
}
int main()
{
	char a = 128;
	printf("%u\n", a);
	return 0;
}
int main()
{
	int i = -20;
	unsigned int j = 10;
	printf("%d\d", i + j);
	return 0;
}
int main()
{
	unsigned int i;
	for (i = 0; i >= 0; i--)
	{
		printf("%u\n", i);
	}
	return 0;
}
#include<string.h>

int main()
{
	char a[1000];
	int i = 0;
	for (i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;

	}
	printf("%d\n", strlen(a));
	return 0;
}
unsigned char i = 0;
int main()
{
	for (i = 0; i <= 255; i++)
	{
		printf("hello word\n");
	}
	return 0;
}

浮点数在内存的存储

常见的浮点数

3.1415926
1E10

一个例子

在这里插入图片描述

可能以为结果会是这样
在这里插入图片描述
但是我们的结果竟然是这样的
在这里插入图片描述
这里就说明了浮点数和整数在内存中存储的方式一定是有区别的

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

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

举例来说
十进制的9.5,写出二进制1001.1,相当于1.0011x2^3
按照上面v的格式,可以得到S=0,M=1.0011,E=2;
如果是-9.5 ,S=1,其他没变

IEEE规定

对于32位的浮点数,最高位的1位是符号位,接着的8位是指数位,剩下的23位位有效数字M

在这里插入图片描述

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

IEEE754对有效数字M和指数E,还有一些特别规定

前面说过。1<=M<=2,也就是说M可以写成1.xxxxxxxxx的形式,其中xxxxxxxx表示小数部分。
IEEE754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxxxx部分。

等到读取的时候,再把第一位的1加上去,这样做的目的,时节省一位有效数字,以32位浮点数为例,留给M只有23位,
将第一位舍去以后,等于可以保存24位有效数字

至于指数E,情况就比较复杂E

首先,E位一个无符号整数(unsigned int)
这意味着,如果E为8为,它的取值范围为0~255,如果E为11位,它的取值范围位0-2047,但是我们知道,科学计数法中的E可以出现负数的,

所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数时127,对于11位的E,这个中间数是1023

比如,2^10的E是10,所以保存位32位浮点数时,必须保存位10+127=137,即10001001;

指数E从内存中取出来还可以再分成三种情况

E不全为0或不全为1

这时,浮点数就采用下面这种规则,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1

比如0.5二进制为0.1根据浮点数的规则存储在内存中,1.0*2^(-1),S=1,M=1.0,E=-1+127=126,表示为01111110,(M的1不存储,只存储小数位,不够23位后面补0
0 01111110 00000000000000000000000

E全为0

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

E全为1

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

讲到这里你懂了为什么刚才那个代码不是我们所想的答案了吗?

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值