C语言进阶-数据的储存

#本章重点

详细解读数据在内存中是怎么存储的

数据类型

//整型
	char				//存的是ascii值
	signed char			//有符号的char类型
	unsigned char		//无符号的char类型
	short
	signed short
	unsigned short		
	int
	signed int
	unsigned int
	long
	signed long
	unsigned long
	long long
	signed long long
	unsigned long long
	int a=10;
	//默认int前面有signed,其他的也是这样的
//浮点型
	float
	double
	long double
//构造类型(自定义类型)
	数组
	结构体类型(struct)
	枚举(enum)
	联合体(union)
//指针类型
	int*
	char*
	void*	
	.....
//空类型
	void	//没有具体指定的类型,通常用于函数返回值,函数参数,指针类型

整型在内存中的存储

变量的创建是要在内存中开辟空间的

int main()
{
	int a = 20;
	//00000000000000000000000000010100
	//0x00000014
	//14 00 00 00
	int b = -10;
	//整数在内存中是以补码存放的
	//对于正整数来说,原码反码补码都相同
	//对于负整数来说,补码是要计算的
	//int类型是4个字节
	//32个比特位
	//10000000000000000000000000001010	原码
	//11111111111111111111111111110101	反码(将原码的符号位不变,其他位按位取反)
	//11111111111111111111111111110110	补码(反码加一)
	//用16进制表示就是
	//f6 ff ff ff
	return 0;
}

在这里插入图片描述

为什么要用补码呢,使用补码可以将符号位和数值域统一处理,又cpu只有加法器

用原码计算1+(-1)
00000000000000000000000000000001		1的原码
10000000000000000000000000000001		-1的原码
10000000000000000000000000000010		得到的-2
用补码计算
00000000000000000000000000000001		1的补码
10000000000000000000000000000001		-1的原码
11111111111111111111111111111110		-1的反码
11111111111111111111111111111111		-1的补码
相加得到
100000000000000000000000000000000		得到33位的结果,舍掉最高位就得到0的补码
00000000000000000000000000000000

大、小端字节序存储

大端字节序存储

数据的低位保存在内存的高地址中,数据的高位保存在内存中的低地址处

在这里插入图片描述

小端字节序存储

数据的低位保存在内存的低地址中,数据的高位保存在内存中的高地址处

在这里插入图片描述
在这里插入图片描述

判断数据在内存中怎么存储的

int main()
{
	int a = 0x11223344;
	char c = (char)a;	//这种方法是错误的,数值在char的范围内是不会发生改变的
	if (c == 0x44)
	{
		printf("小端存储\n");
	}
	elsex
		printf("大端存储\n");
	return 0;
}

在这里插入图片描述

当前vs2019中是小端存储的

//写成函数
int check_sys()
{
	int a = 1;
	return *(char*)&a;
}

int main()
{
	int ret = check_sys();
	if (ret == 1)
	{
		printf("小端存储\n");
	}
	else
		printf("大端存储\n");
	return 0;
}

练习

在这里插入图片描述

a,b是一样的
11111111	-1的补码
%d表示int类型,char要整型提升
按原符号位提升
11111111111111111111111111111111	-1的补码
11111111111111111111111111111110	-1的反码
10000000000000000000000000000001	-1的原码(在屏幕上显示的)
c
无符号数整型提升前面补0
00000000000000000000000011111111	255

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

int main()
{
	unsigned int i = 0;
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
	}
	return 0;
}
//无符号数>=0,条件恒成立,程序会变成死循环

在这里插入图片描述

这是因为当i等于129时,arr[130]=-130
100000000000000000000010000010		-130的原码
111111111111111111111101111101		反码
111111111111111111111101111110		补码
在截取
01111111							这是126
当i等于131时,arr[131]=-132
100000000000000000000010000100
111111111111111111111101111011
111111111111111111111101111011
再截取
01111011							这是123
以此类推,当i等于255时,arr[256]=-256
100000000000000000000100000000
111111111111111111111011111111
111111111111111111111100000000
截取
00000000							这是0
strlen是以'\0'停止的,'\0'的ascii码值是0
所以循环了255次,结果就是255
unsigned char i = 0;

int main()
{
	for (i = 0; i <= 255; i++)
	{
		printf("hello world\n");
	}
	return 0;
}
//死循环
//当i=256时,i超过了unsigned char的取值范围了,i又变成0了

浮点数在内存中的存储

浮点型
float
double
long double

整型取值范围在limits.h中定义的
浮点型取值范围在float.h中定义的

十进制小数转换成二进制

整数转换就不说了
看小数部分
例如22.75
整数部分是10110
小数部分0.75
用小数部分乘以2,结果大于1,取1,小于10
0.75*2=1.51
0.5*2=1.01
结果就是10110.11
在算一个1.625
小数部分
0.625*2=1.251
0.25*2=0.50
0.5*2=1.01
结果就是1.101
小数部分是按照顺序排列的

浮点型在内存中到底是怎么存储的呢

在这里插入图片描述

可以看出结果是大不相同的,这就说明了浮点型和整型在内存中的存储是不同的

浮点数在内存中的存储是由国际标准IEEE(电气和电子工程协会)754制定的
任意一个二进制浮点数V都可以表示成下面的形式:
(-1)^S * M * 2^E
(-1)^S 表示符号位,当S=0时,V为整数,当S=1时,V为负数
M代表有效数字,大于等于1,小于2
2^E表示指数位
例如5.5,二进制表示是101.1
用上面的标准就可以写成1.011*2^2
正数,(-1)^S等于0,S=0
1.011是M
E就是2

在这里插入图片描述

对于double型,S也是1个比特位,但是E是11个比特位,M是52个比特位

在科学计数法中是可以出现负数的,对于单精度浮点数来说,存入内存中的E要加上127,双精度浮点数加上1023,从内存中取出来的时候在减去

5.5在内存中的存放
5.5的二进制是101.1
1.011*2^2
s=0,e=2,m=011
01000000101100000000000000000000 
16进制就是
0100 0000 1011 0000 0000 0000 0000 0000
40 B0 00 00
小端存储就是
00 00 B0 40

在这里插入图片描述

两种特殊情况

E全0
全为0,表示E等于1-127,这是一个无限接近于0的数字,即无穷小,此时M小数前的1不要了
E全为1
全为1,表示E等于255-127=128,这是一个非常大的数字,即无穷大

现在就可以解决最前面的题了

int main()
{
	int n = 9;
	//00000000000000000000000000001001
	float* p = (float*)&n;
	printf("n的值为:%d\n", n);			//9
	//以浮点数打印就会认为n里面放的是浮点数
	//0 00000000 00000000000000000001001
	//(-1)^0*(1-127)*(0.00000000000000000001001)
	//最多打印小数点后面的六位,所以打印出来的是0.000000
	printf("*p的值为:%f\n", *p);		

	*p = 9.0;
	//现在是用浮点数的存储方式存储9.0
	//1001.0  1.001*2^3
	//s=0,e=3,m=011
	//0 10000010 00100000000000000000000
	//16进制就是
	//0100 0001 0001 0000 0000 0000 0000 0000
	//41 10 00 00
	//小端存储
	//00 00 10 41
	printf("n的值为:%d\n", n);		//当成整型打印,这是一个很大的数
	printf("*p的值为:%f\n", *p);	//9.000000
	return 0;
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值