数据在内存中的存储------大小端字节序+char类型的取值范围篇

🐍相信大家初学编程对数据在内存中是怎么存储的有很多疑问与不解,今天我专门针对这些痛点做出了一些 解决与学习 办法,帮助大家来深入理解数据在内存中是怎么存储的,因为设计到的知识点比较干货,所以一定要认真看哟,保证你可以收获满满!!!

常见的数据类型有哪些?

  • c语言里我们知道常用的数据类型有:
char      //字符类型(1个字节)
short     //短整型(2个字节)
int       //整型(4个字节)
long      //长整型(4个字节)
long long //长长整型(8个字节)
float     //浮点型(4个字节)
double    //双精度浮点型(8个字节)
  • 划分这些内置数据类型有啥意义呢?
    1、我们使用上面某个内置类型的时候,在内存里开辟空间的大小不同
    2、如何看待内存的视角(假如我们用float创建了一个变量,那在内存里它就会认为我们创建了一个小数,假如我们用int创建了一个变量,那在内存里它就会认为我们创建了一个整数,其它以此类推)
    🐍注:通常我们创建的变量的地址都是数据类型的第一个字节的地址!!!

内存中原码、反码、补码是什么?(这个一定要理解!32位机器)

  • 🐍只有负数才有原码、反码、补码的概念;正数的原码、反码、补码就是它本身代表的二进制序列!

原码:就是一个正常的整数的二进制序列。
反码:就是二进制序列的符号位(符号位就是二进制序列的第一位——0代表整数,1代表负数)不变,其它位 按位取反。
补码(事实上在内存里它存的就是这个数据的二进制补码形式):就是反码 + 1。

  • 原反补的概念其实就是数据在内存里的二进制序列
    • 首先来看一个整型的例子:
#include<stdio.h>
int main()
{
	int a = 10;
	//这是十进制的10,我们知道在计算机里它只能识别二进制 0 或 1 组成的数字
	//为了方便大家看,这里就把32位的二进制序列分为1个字节1个字节的形式啦
	//原码:00000000 00000000 00000000 00001010
	//反码:00000000 00000000 00000000 00001010
	//补码:00000000 00000000 00000000 00001010
	//因为10是正数,所以它的原反补就是它本身的二进制序列!
    int a = -10;
    //原码:00000000 00000000 00000000 00001010
    //反码:01111111 11111111 11111111 11110101
    //补码:01111111 11111111 11111111 11110110
    //因为-10是负数,所以以上的三个二进制序列就是它的原反补 的表现形式
    //在内存里存的就是它的补码:
    //补码:01111111 11111111 11111111 11110110
}

大小端字节序存储是什么?

  • 我们在vs调试内存的时候是不是总是有一些疑问——比如拿10举例子:为什么我存进去的明明是——00000000 00000000 00000000 00001010 但内存里却显示0a 00 00 00(我们在内存里一般用十六进制表示形式)那就算是这样的话,那不也应该是——00 00 00 0a嘛!为什么跟我们想要的效果不一样?
    在这里插入图片描述

  • 这里面其实就涉及到了大小端字节序存储的概念:

    • 大端字节序存储:把一个数据的低位字节的内容 存放在 高地址处,高位字节的内容 存放在 低地址处。
    • 小端字节序存储:把一个数据的低位字节的内容 存放在 低地址处,高位字节的内容 存放在 高地址处。
    • 那什么是 高低 位字节内容呢?比如一个十进制数字234——4是个位、3是十位、2是百位,那很显然最右边的就是低位字节内容,而最左边的就是高位字节内容!
    • 既然都是大小端字节序存储了,那肯定都是以字节为单位的,请看下图:
      在这里插入图片描述
      在这里插入图片描述
    • 其实这里面是有一些故事背景存在的,感兴趣的朋友可以去看一下这个小说——《格列夫游记》
  • 当了解了什么是大小端字节序存储了之后,那我们就可以写一个小程序 来判断一下当前机器是大端还是小端啦:

int check_sys(void) //函数无参
{
	//我们就用 1 来举例子,比较容易,因为只是判断一下是大端还是小端,别为难自己!!!
	int i = 1;
	//我们把 &i 强制类型转换成 char* 类型的,然后 *解引用 访问到 char*指针指向的那个对象的1个字节
	return (*(char*)&i); //如果返回的是 1 那就是小端,否则直接就是大端
}
int main()
{
	int  ret = check_sys( );
	if(ret==1)
	{
		printf("当前机器是小端\n");
	}
	else
	{
		printf("当前机器是大端\n");
	}
	return 0;
}
  • 🐍相信到这里咱们应该就理解什么是大小端字节序存储了吧,如果哪里不懂的,也可以私信问我,看到了准儿 马上立刻 回答你!!!

char类型的取值范围是多少?

  • 请看这个式子:char a = 128;
    这个式子乍一看没啥毛病,但实际上它是有毛病的。
    我们说char类型是 1 个字节的大小—那就是8个bit位,并且上面的那个表达式是有符号的。
    那么请看图:

    在这里插入图片描述
    所以当char是有符号的char的时候,实际上它本身是存不进去128的,所以肯定会发生截断
    截断:数据字节大的内容,放到数据字节小的内容里,二进制位根据数据的大小进行截断
    注意:
    原码 - 按位取反得反码 - 反码+1得补码——我们简称这个过程叫 按位取反+1
    但是从补码到原码也可以用 按位取反+1来从补码得到原码,不过这里的按位取反就不是得到反码了,谁知道它得到的是什么呢?反正最后可以得到原码就对了!!!

    请看代码:
int main()
{
	char a = 128;
	// 128是一个十进制整数,它要放到char类型的空间里的话,必然会发生截断!
	//128的补码:00000000 00000000 00000000 10000000
	//这里128的二进制是32个bit位,但char类型的大小只能占有8个bit位,所以会发生截断!
	//截断后:10000000 - -128
	//然后我们又要用%d打印出来,那就会发生整型提升。
	//整型提升规则:如果是无符号数那高位直接补0;如果是有符号数,那它就会把高位的数看成符号位
	//然后直接按符号位补齐32个bit位
	//上边的char a默认是有符号的,所以它会把10000000中的1看成符号位,然后直接补齐。
	//补齐后:
	//11111111 11111111 11111111 10000000 - 补码
	//10000000 00000000 00000000 01111111 - 不是反码
	//10000000 00000000 00000000 10000000 - 原码           
	printf("%d\n",a); // 所以打印出来的就是-128
}
  • 那其实无符号的char也是上面那个图展示的样子,只不过是没有符号位,所有的位,都代表值,那就不存在原反补的概念了,因为原反补都是它本身代表的二进制序列!!!
    • 那其实无符号char的取值范围就是0 - 255。

    00000000 - 0
    00000001 - 1

    011111111 - 127
    10000000 - 128

    11111111 - 255

    结语

    好啦,那今天讲的大小端字节序存储和char类型的取值范围,我应该也讲得差不多了!如果哪里不明白的一定要私信我,也可以纠正我的错误,反正别不吭声,只有交流才能共同进步,让我们共同进步吧那就!!!

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值