端序或字节序问题

端序也称为字节序,分为:

  • 大端,也叫网络端
  • 小端

举个例子,假设现有两个字节的数据: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 即大端序/网络序,反之即小端序

其他:

  • 转换端序就是把字节序对调,那么原本是小端序,转换端序后就变成大端序,反之则反
  • 按照常规约定,当使用网络传输数据时,对于多字节数值都使用大端序,所以大端序也称之为网络序
  • 不过实际应用中使用网络传输数据时并不一定为大端,只要收发数据的双方约定好,用大端还是小端都无所谓,自行处理就好