端序或字节序问题
端序也称为字节序,分为:
- 大端,也叫网络端
- 小端
举个例子,假设现有两个字节的数据:0xFF, 0x7E
(十六进制 dump),这两个字节表示一个 short/int16_t
类型的数字
在内存中会把数字的两个字节分开存储,每个字节所在的内存都有其内存地址,内存地址又分为 低位地址 和 高位地址,在十六进制 dump 中,从左向右的顺序,就是内存地址从低到高的顺序
表示数值的字节数据则分为 低位字节 和 高位字节,低位字节在右,高位字节在左(注意顺序与内存地址顺序相反),比如 0xFF7E
(注意中间没有逗号,这里指从数值角度看这个数,而不是字节角度)这个数中的低位字节是 0x7E
,反之高位字节是 0xFF
CPU 总是按照内存地址从低到高(从左向右)的顺序读取每一个字节,当 CPU 要将连续读到的两个(或更多)字节合并为一个数值时(多字节数值类型 short/int16_t),就涉及到了字节端序问题:
- 将先读到的字节作为 低位字节,后读到的字节作为 高位字节 时,就是小端
- 即:当 低位地址 上是 低位字节,高位地址 上是 高位字节 时,就是小端(现在的 CPU 一般都是按照小端序处理多字节数值)
- 相反,当 低位地址 上是 高位字节(高位地址 上是 低位字节)时,就是大端/网络端
那么,本例中两个字节的数据 0xFF, 0x7E
(十六进制 dump)在不同端序下分别表示的数值为:
- 小端序:0x7EFF = 32511
- 大端序:0xFF7E = 65406
有一个比较容易记住的技巧:
人类习惯的文字读取顺序其实是大端序,比如本例中两个字节的数据:0xFF, 0x7E
,如果按照人类习惯读取出来就是 0xFF7E
即大端序/网络序,反之即小端序
其他:
- 转换端序就是把字节序对调,那么原本是小端序,转换端序后就变成大端序,反之则反
- 按照常规约定,当使用网络传输数据时,对于多字节数值都使用大端序,所以大端序也称之为网络序
- 不过实际应用中使用网络传输数据时并不一定为大端,只要收发数据的双方约定好,用大端还是小端都无所谓,自行处理就好