小端模式和大端模式_嵌入式C语言——大小端模式初探

引言:什么是大小端模式

在计算机通信过程中,经常会遇到一个问题,是先发送数据的高字节还是先发送低字节呢?比如我们经常可以在网络通讯协议中,都能听到”大端(big endian)模式”这一词,与之对应的是"小端模式(little endian)",发送方和接收方必须按照相同的字节顺序来处理数据,否则就会出现错误。

而今天我们主要讲的是计算机存储系统的大小端,在计算机内存/硬盘中,数据是以字节为单位存储的,于是乎有一个32位的二进制在内存中存储时就有2种方式分布:1.高字节对应高地址(大端模式) 2.高字节对应低地址(小端模式), 以下示意图,感受下区别:

862528762fc99d64bf1ad6b3281e516b.png

经典笔试题:测试当前机器的大小端模式

上一篇我们详细讲解了共用体union的一些概念,如定义,使用,内存分布等等知识点,今天我们就趁热打铁,使用共用体union来测试我们机器的大小端模式,先贴代码:

#include union test{int a;char b;};//返回值:// 1:小端模式  // 0: 大端模式int Is_Little_Endian(void){union test t1;t1.a = 1;return t1.b;}int main(void){int ret = Is_Little_Endian();if(ret == 1)printf("我的机器是小端模式!");elseprintf("我的机器是大端模式!");return 0;}

代码是不是很简单呢~, 我们来简单分析下:

1. 首先我们定义函数int Is_Little_Endian(void),其作用就是来测试当前机器的大小端的

  1. 我们在函数体中定义了共用体t1, 并初始化了t1.a=1; 并直接返回了t1.b
  2. 我们在主函数main中定义ret变量来接收上面函数返回的t1.b的值
  3. 根据ret的值,我们判断机器的大小端,并打印相关信息

相信这里大家有个疑惑,凭啥就能根据t1.b的值就能判断机器的大小端勒? 这里有一个很重要的概念,即共用体的本质:共用体内元素不独立,元素之间共享同一块内存空间,只是解析不同!!!,我们通过下图来感受下其道理:

11a3272149bb479f0bd0db2c9e3b802a.png

注意共用体t1中元素b是char类型,只占用第一个字节(内存地址为0x8的一个格子),因此我们可以根据t1.b的值来判断机器的大小端。

编译运行:

b74df06a70be4787c6ccfb3a5089a188.png

我的测试机器就是英特尔的x86_64,就是小端模式,与运行结果一致。

到这里如果大家还是怀疑上面代码的测试的可靠性,我特意下载了keil c51来验证下,同样我们将以上的代码原封不动贴到Keil4 C51(机器设置为AT89C51RC,相信大家对这款单片机型号不陌生吧, 满满的回忆~~):

888a88a3d8c9ac09fd3615edfce1478f.png

OK,我们软件仿真下:

fdf8bcb8c6fe8f5543dfc39eefe22862.png

简单分析下:

1. 分别打了2个断点(上图红色标记处),然后单步运行

  1. 可以看到单步到if判断语句时,跳转到else之后的代码,打印了printf("我的机器是大端模式!");
  2. 即说明AT89C51RC是大端模式

用指针方式测试大小端

#include union test{int a;char b;};//返回值:// 1:小端模式  //其他: 大端模式int Is_Little_Endian2(void){int a = 1;char b = *((char *)(&a));return b;}int main(void){int ret = Is_Little_Endian2();if(ret == 1)printf("我的机器是小端模式!");elseprintf("我的机器是大端模式!");return 0;}

简单分析:

1. 在Is_Little_Endian2函数体中, 我们定义int a,并赋值为1

  1. 我们将a取地址后,强制转化成char *类型,即由原来执行一个int类型(4个格子)变为指向一次char类型(1个格子)的内存空间。然后解引用后赋值给b
  2. 函数返回b的值,并根据b的值判断机器的大小端

编译运行:

2f4076b942d98d15e2be83a62f11e3bc.png

结果还是一样的,同样用内存示意图加深理解:

5f27f94d3ce7df04d0a39a9ebfe36e50.png

小结

大端模式和小端模式本身没有对错,没有优劣,理论上按照大端或小端都可以,但是要求必须存储时和读取时按照同样的大小端模式来进行,否则会出错。

现实的情况就是:有些CPU公司用大端(譬如C51单片机;有些CPU用小端(譬如ARM)(起始大部分是用小端模式),当不知道当前环境是用大端模式还是小端模式时就需要用代码来检测当前系统的大小端。

0513dc8cdbf7c62a5d7e4ad792514ded.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值