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

目录

 一、数据类型介绍

二、数值类型的范围

1.unsigned char 与signed char 范围

 2.unsigned short 与signed short 范围

 三、原码、反码、补码

四、整形在内存中的存储

五、大小端字节序

六、经典例题


 一、数据类型介绍

//整型家族:
char //字符数据类型
short //短整型
int //整型
long //长整型
long long //更长的整型
 
//浮点型家族
float //单精度浮点型
double //双精度浮点型
 

 类型的意义:
1. 使用这个类型开辟内存空间的大小(大小决定了使用范围)。
2. 如何看待内存空间的视角。

比如:

 

int 开辟4个字节的空间,float 也是开辟4个字节的空间,但是从内存空间的视角来看,

变量a里面存放的是整数,变量f里面存放的是小数 

二、数值类型的范围

1.unsigned char 与signed char 范围

 2.unsigned short 与signed short 范围

 三、原码、反码、补码

计算机中的整数有三种表示方法,即原码、反码和补码。
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,
负整数的三种表示方法各不相同。
原码
直接将数值按照正负数的形式翻译成二进制就可以。
反码
将原码的符号位不变,其他位依次按位取反就可以得到了。
补码

反码+1就得到补码。

正数的原、反、补码都相同。

四、整形在内存中的存储
 

整数可以写出三种2进制表示形式:
原码:直接将数值按照正负数的形式翻译成二进制就可以
反码:将原码的符号位不变,其他位依次按位取反就可以得到了
补码:反码+1就得到补码。
 
正整数的原码、反码、补码相同
负数的原码、反码、补码是需要计算的

int main()
{
	//int a = 10;//整型值
	//原码:00000000000000000000000000001010
	//反码:00000000000000000000000000001010
	//补码:00000000000000000000000000001010

	int b = -10;//整型值
	//原码:10000000000000000000000000001010
	//反码:11111111111111111111111111110101
	//补码:1111 1111 1111 1111 1111 1111 1111 0110
	//      F    F    F     F   F     F    F   6
	//0xff ff ff f6
	//
	return 0;
}



int main()
{
	1 - 1;
	//1-1
	//1+(-1)
	//使用补码的二进制计算
	// 00000000000000000000000000000001
	// 11111111111111111111111111111111
	//100000000000000000000000000000000
	// 00000000000000000000000000000000
	// 0
	// 10000000000000000000000000000001   -1的原码
	// 11111111111111111111111111111110   -1的反码
	// 11111111111111111111111111111111   -1的补码
	// 
	// 使用原码计算是错误的
	//00000000000000000000000000000001
	//10000000000000000000000000000001
	//10000000000000000000000000000010 
	// 
	//CPU 只有加法器
	//
	return 0;
}



#include <stdio.h>

int main()
{
	unsigned int ch = -10;
	//-10
	//10000000000000000000000000001010
	//11111111111111111111111111110101
	//11111111111111111111111111110110
	//
	//printf("%u\n", ch);//%u是打印无符号数,意思是你要我打印的一定是无符号数,不是无符号数,我也认为是无符号数
	printf("%d\n", ch);//%d 是打印有符号数,意思是你要我打印的一定是有符号数,不是有符号的数,我也认为是有符号数
	return 0;
}

五、大小端字节序

什么是大端小端:
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址
中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地
址中

如何判断自己的电脑是大端存储还是小端存储:

int check_sys()
{
	int a = 1;
	char* p = (char*)&a;

	if (*p == 1)
	{
		return 1;//小端
	}
	else
	{
		return 0;//大端
	}
}


int check_sys()
{
	int a = 1;
	char* p = (char*)&a;
	return *p;
}

int check_sys()
{
	int a = 1;
	return *(char*)&a;
}

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

VS2019就是小端存储 :

六、经典例题

//程序的执行结果为( )
int main()
{
  unsigned char a = 200;
  unsigned char b = 100;
  unsigned char c = 0;
  c = a + b;
  printf(“%d %d”, a+b,c);//300 44
  return 0;
}
//思路:
//128 + 64 +8
//00000000 00000000 00000000 11001000
//11001000 200
// 64 + 32 +4
//00000000 00000000 00000000 01100100
//01100100 100
//00000000 00000000 00000001 00101100
//00101100 32 + 8 + 4

题解:

printf在传入参数的时候如果是整形会默认传入四字节,所以a+b的结果是用一个四字节的整数接收的,不会越界。而c已经在c = a + b这一步中丢弃了最高位的1,所以只能是300-256得到的44了

由于printf是可变参数的函数,所以后面参数的类型是未知的,所以甭管你传入的是什么类型,printf只会根据类型的不同将用两种不同的长度存储。其中8字节的只有long long、float和double(注意float会处理成double再传入),其他类型都是4字节。所以虽然a + b的类型是char,实际接收时还是用一个四字节整数接收的。另外,读取时,%lld、%llx等整型方式和%f、%lf等浮点型方式读8字节,其他读4字节。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值