字节序

什么是字节序

最近在看tcp通信相关的知识,期间看了好几个仓库都出现了字节序的概念,所以就想着整理一下字节序的相关知识。

字节序是指数据在内存中的存储顺序。

所有的数据在计算机中的存储本质上就是一串二进制数据,而字节序就是指这串二进制数据在内存中的存储顺序。

字节序列分为大端序小端序

  • 大端序是指高位字节在前,占据内存中的低地址。
  • 小端序是指低位字节在前,占据内存中的高地址

来张图就明白了:

byte_order desc

假设现在有个16进制的数据0x01020304,那么在大端序的字节序中,内存中的存储顺序就是01 02 03 04,而在小端序的字节序中,内存中的存储顺序就是04 03 02 01

再举个例子,换成10进制的数据110,那么在大端序中,内存中的存储顺序为1 1 0,而在小端序中,内存中的存储顺序为0 1 1

一个最高为放在前面,一个最低位放在前面,这就是字节序的区别。

大端序和小端序的应用场景

小端序优点

  • 一般用于cpu内部的计算。因为数字的计算一般都是从低位开始的,所以小端序的计算效率更高。比如我们计算加法都是从个位数开始计算。
  • 对一个值的内存占用进行扩大或缩小时,小端序的处理方式更加简单。比如我们要把一个int类型的数据转换成short类型的数据,那么只需要取低位的两个字节就可以了。

大端序优点

  • 主要用于网络传输。比如在tcp通信中,会在头部加上包大小,内核收到该字节序时,会提前知道包的大小,从而提前分配内存,提高效率。
  • 更加符合人类的书写方式,便于理解。

go代码演示

go语言中提供了encoding/binary包来处理字节序的问题。

大端序使用BigEndian,小端序使用LittleEndian

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
var num int32 = 0x01020304
fmt.Printf("origin num - %+v, %x\n", num, num)

bigBytes, littleBytes := make([]byte, 4), make([]byte, 4)
binary.BigEndian.PutUint32(bigBytes, uint32(num))
binary.LittleEndian.PutUint32(littleBytes, uint32(num))

// output
fmt.Printf("big endian - %+v, %x\n", bigBytes, bigBytes)
fmt.Printf("little endian - %+v, %x\n", littleBytes, littleBytes)
  1. 声明一个int32类型的变量num,值为0x01020304
  2. 使用BigEndianLittleEndian分别将num转换成字节序列。

最终输出的结果:

1
2
3
origin num - 16909060, 1020304
big endian - [1 2 3 4], 01020304
little endian - [4 3 2 1], 04030201
updatedupdated2024-01-252024-01-25