通信协议中的数据传输、数组的存储方式以及数据的强制转换等问题都会涉及到大小端的区分。
大小端模式在计算机系统中被广泛应用,但仍有许多人对此不太了解。在这里我们将进行简单的普及。
一、大小端模式的起因
在计算机系统中,数据以字节为单位进行处理,每个地址单元对应一个字节(8位)。
然而,在C语言中除了8位的char型之外,还有16位的short型和32位的int型等。对于位数大于8位的处理器,例如16位或32位的处理器,寄存器的宽度大于一个字节,这就引发了如何存储多个字节的问题。于是,大端存储模式和小端存储模式应运而生。
以一个16位的short型变量x为例,在内存中的地址为0x0010,其值为0x1122。其中0x11是高字节,0x22是低字节。
在大端模式下,0x11会被存储在低地址中,即0x0010;0x22会被存储在高地址中,即0x0011。而小端模式则正好相反。
简而言之,大小端模式是为了解决多字节数据在内存中的存储问题。
二、什么是大端和小端?
大端模式:是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。
小端模式:是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。
假如32位宽(uint32_t)的数据0x12345678,从地址0x08004000开始存放:
地址 | 小端存放内容 | 大端存放内容 |
---|---|---|
0x08004003 | 0x12 | 0x78 |
0x08004002 | 0x34 | 0x56 |
0x08004001 | 0x56 | 0x34 |
0x08004000 | 0x78 | 0x12 |
再结合一张图进行理解:
从上面表格、图可以看得出来,大小端的差异在于存放顺序不同。
在维基百科中还有有一段关于“端的起源”:
三、数组在大端小端情况下的存储
以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value。
1.大端模式下
地址 | 数组 | 值 | 位置 |
---|---|---|---|
高地址 | buf[3] | 0x78 | 低位 |
– | buf[2] | 0x56 | – |
– | buf[1] | 0x34 | – |
低地址 | buf[0] | 0x12 | 高位 |
2.小端模式下
地址 | 数组 | 值 | 位置 |
---|---|---|---|
高地址 | buf[3] | 0x12 | 低位 |
– | buf[2] | 0x34 | – |
– | buf[1] | 0x56 | – |
低地址 | buf[0] | 0x78 | 高位 |
不知道大家对数组进行强制转换成整型数据没有?
如果你要进行强制转换,肯定要考虑大小端问题。
四、大小端谁更好?
小端模式:强制转换数据不需要调整字节内容,1、2、4字节的存储方式一样。
大端模式:符号位的判定固定为第一个字节,容易判断正负。
总结:大端小端没有谁优谁劣,各自优势便是对方劣势。
五、常见字节序
常见的操作系统是小端,通讯协议是大端。
1.常见CPU的字节序
大端模式:PowerPC、IBM、Sun
小端模式:x86、DEC
ARM既可以工作在大端模式,也可以工作在小端模式。
(内容来自网络)
2.STM32属于小端模式
测试一款MCU属于大端,还是小端方法很多种,通过打印数据,通过在线调试查看数据:
当然,在MCU的手册中也有相关说明。
六、大小端转换
开篇说了,实际应用中,大小端应用的地方很多通信协议、数据存储等。如果字节序不一致,就需要转换。
只要你理解其中原理(高低顺序),转换的方法很多,下面简单列列两个。
**
**
1.对于16位字数据
#define BigtoLittle16(A) (( ((uint16)(A) & 0xff00) >> 8) | \
(( (uint16)(A) & 0x00ff)
2.对于32位字数据
#define BigtoLittle32(A) ((( (uint32)(A) & 0xff000000) >> 24) | \
(( (uint32)(A) & 0x00ff0000) >> 8) | \
(( (uint32)(A) & 0x0000ff00)
方法很多种,感兴趣的朋友可自行研究。本文就写到这里,希望对你有帮助。
以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !