【C语言】大小端介绍以及判断大小端的两种方式

前言
🎈大家好,我是何小侠🎈
🍃大家可以叫我小何或者小侠🍃
💐希望能通过写博客加深自己对于学习内容的理解💐
🌸也能帮助更多人理解和学习🌸

花繁柳密处,拨得开,才是手段;风狂雨急时,立得定,方见脚根。
解释:在花繁叶茂、柳密如织的美丽和复杂情境下,如果还能不受束缚,来去自如,才是有手段、有办法的人。在狂风骤雨的狼狈状态下还能站稳脚跟,不被吹倒,才是真正有原则的大英雄。

在这里插入图片描述


    这篇博客我们将会了解到数据在内存中的存储方式。这对我们调试和理解内存都有很大好处。
    在这里插入图片描述

    例子展示⁉️

    在这里插入图片描述
    我们把10这个整型存储在变量a中, 把-10存储在变量b中。
    我们动手写一下就知道10存储在a中的补码是

    0000 0000 0000 0000 0000 0000 0000 1010 (原码反码补码)

    转换为十六进制就是== 00 00 00 0a==

    -10的原码是

    1000 0000 0000 0000 0000 0000 0000 1010 (原码)

    1111 1111 1111 1111 1111 1111 1111 0101 (反码)

    1111 1111 1111 1111 1111 1111 1111 0110(补码)

    转换为十六进制就是== FF FF FF F6==

    调试起来看看内存
    在这里插入图片描述
    不应该是 00 00 00 0aFF FF FF F6吗?
    下面我们来解释一下。

    大端小端是什么呢?😶‍🌫️

    大端(存储)模式小端(存储)模式
    将数据的高位存放到内存的低地址 ,数据的低位存放到内存的高地址将数据的高位存放到内存的高地址,数据的低位存放到内存的低地址

    也许这样说你可能不是很理解不要紧,下面我会画图讲解:在这里插入图片描述
    在这里插入图片描述
    首先我们要知道一个叫字节序的概念:
    0x22334455
    在这里插入图片描述
    这就是字节序,和高位低位的概概念

    我们将0x22334455存放到a变量中,那么小端是怎么样呢?
    在这里插入图片描述
    那么大端就很明显了
    在这里插入图片描述
    这里补充一句:

    对于一个字节的数据,它只有一个字节,没有字节序的概念。字节序是指多字节数据在内存中的存储顺序,而一个字节的数据只有一个字节,没有多个字节需要进行存储顺序的考虑。

    为什么存在大小端呢?🚩

    为什么会有大小端模式之分呢?
    这是因为在计算机系统中,我们是以字节为单位的,
    每个地址单元 都对应着一个字节,一个字节为8 bit。
    但是在C语言中除了8 bit的char之外,
    还有16 bit的short型,
    32 bit的long型(要看具体的编译器),
    另外,对于位数大于8位 的处理器,
    例如16位或者32位的处理器,
    由于寄存器宽度大于一个字节,
    那么必然存在着一个如何将多个字节安排的问题。
    因此就 导致了大端存储模式和小端存储模式。

    那为什么我们在例子展示的时候,只是小端呢?
    这样因为C语言并没有明确规定要怎么存储,大端小端是由编译器决定的。

    判断大小端的两种方法

    方法一

    我们直接上代码:

    int jugde(int a)
    {
    	char* str = (char *) & a;
    	if (*str == 1)
    	{
    		return 1;
    	}
    	else
    	{
    		return 0;
    	}
    
    }
    int main()
    {
    	int a = 0x1;
    	int i = jugde(a);//返回1为小端,返回0为大端
    	if (i)
    	{
    		printf("小端\n");
    	}
    	else
    		printf("大端\n");
    
    	return 0;
    }
    

    其实是比较简单的,
    我们知道a = 0x00 00 00 01;
    那么如果是小端存储 在内存中就是 01 00 00 00
    我们将a 变量的值传到 judge 函数中,judge函数会创建一个新的变量a来接受0x 00 00 00 01,我们用一个char * 类型的指针指向a,或者说把a的地址放到str变量中,为什么是char * 类型呢?
    我们知道指针类型决定了

    • 指针变量解引时能访问多少个字节,
    • 和指针±的步长为多大。

    这里明显就是和访问字节相关,
    char * 类型的指针能访问1个字节
    也就说

    • 如果是小端 * str的值就是1,
    • 如果是小端 *str的值就是0,
      在这里插入图片描述

    是不是很巧妙。还有更巧妙的:
    我们可以改进我们上面的这个代码:

    int jugde(int a)
    {
    	char* str = (char *) & a;
    	
    	return (*str);
    }
    int main()
    {
    	int a = 0x1;
    	int i = jugde(a);//返回1为小端,返回0为大端
    	if (i)
    	{
    		printf("小端\n");
    	}
    	else
    		printf("大端\n");
    
    	return 0;
    }
    

    我们知道 * str的值无非两种,要么是0要么是1,那么为什么不直接返回 * str呢?

    其实还能改进,
    我们能不能不用指针呢?
    当然可以!!

    int jugde(int a)
    {
    	
    	return *(char*)&a;
    
      }
    int main()
    {
    	int a = 0x1;
    	int i = jugde(a);//返回1为小端,返回0为大端
    	if (i)
    	{
    		printf("小端\n");
    	}
    	else
    		printf("大端\n");
    
    	return 0;
    }
    

    我们先取地址a,然后强转为(char *)类型,这样我们解引用的范围就是一个字节了,然后就更上面的方法一样的,确实妙啊在这里插入图片描述~~~。

    第二种方法🦚

    第二种方法运用了联合体!

    int jugde()
    {
    	union test
    	{
    		int a;
    		char b;
    		
    
    	}u;
    	u.a = 1;
    	return u.b;
    
    }
    int main()
    {
    	if (jugde() == 1)
    	{
    		printf("小端\n");
    	}
    	else
    		printf("大端\n");
    	return 0;
    }
    

    我们画图来简单看看:
    在这里插入图片描述
    这样我们就知道return u.b;到底是在干些什么。

    总结🍊

    我们在这篇博客中介绍了什么是大小端,为什么会有大小端,还有大小端的两种巧妙的判断方法,你全都get到了吗?在这里插入图片描述

    最后如果这篇博客有帮助到你,欢迎点赞关注加收藏

    在这里插入图片描述在这里插入图片描述
    如果本文有任何错误或者有疑点欢迎在评论区评论
    在这里插入图片描述

    在这里插入图片描述

    评论 12
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包

    打赏作者

    He XIAO xia

    你的鼓励将是我创作的最大动力

    ¥1 ¥2 ¥4 ¥6 ¥10 ¥20
    扫码支付:¥1
    获取中
    扫码支付

    您的余额不足,请更换扫码支付或充值

    打赏作者

    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

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

    余额充值