最近在读代码的时候对端序(
endianness
)的转换部分产生了一些疑惑,主要原因是对相关知识的理解还不够透彻。查找阅读了一些文献之后,有了更深刻的理解。
在讨论端序之前,我们先规定一些最基本的顺序,这一点很重要。
人的书写以及阅读是从左往右的。
机器读写数据是从低地址到高地址。
类似的,人们习惯按照从高位到低位来表示一个数字,比如数字
256
,百位是
2
,十位是
5
,个位是
6
。再比如一个十六进制数
0x12345678
,最高位是
1
,最低位是
8
。
这种先写(读)高位数据,再写(读)低位数据的顺序,我们称之为 大端序(
Big-Endian
)。字面意思理解,就是把大的放在前面。结合上面对于基本顺序的规定,前面就是人们书写的左边,或者是机器的低地址。
聪明的你肯定马上会想到,那么 小端序(
Little-Endian
)相应的就是先写(读)低位,再写(读)高位。结合上面的例子,对于数字
256
,如果按照
“个十百”
的表示顺序,就应该写成
652
。
计算机中的字节序
然后让我们回到计算机学科中来讨论。虽然计算机中数据的最小表示单位是
比特(bit)
,但由于
现代计算机体系架构的寻址粒度
一般是
字节(byte)
,所以我们所说的端序通常指的是
字节序
。
对于比特位的前后顺序(
Bit Endieanness
),一般在数据序列化的时候讨论,而不是在计算机体系结构中。
所以在本文中,我们规定,字节内的比特位的排列为从高位到低位
。例如,
170
用单字节表示为 (参考
RFC 1700: Assigned Numbers (rfc-editor.org)
):
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|1 0 1 0 1 0 1 0|
+-+-+-+-+-+-+-+-+
上节例子中的十六进制数 0x12345678
,共占用了四个字节,从最高位字节(Most Significant Byte, MSB
)到最低位字节(Least Significant Byte, LSB
)分别为 0x12 0x34 0x55 0x78
。
如果按照 Big-Endian
来存储,假设从左到右为低地址到高地址,那么其在存储设备中存储为:0x12 0x34 0x56 0x78
。如果按照 Little-Endian
来存储,其存储为:0x78 0x56 0x34 0x12
。
直到这里还算是云淡风轻,岁月静好。
小端序的移位操作
对于移位操作,大家应该并不陌生,比如 C
语言中的:
short i = 0x1080 << 1;