聊聊字节序

前面在了解字符编码的时候,遇到了为什么UTF-8没有字节序的问题,这个字节序是什么?为什么UTF-16会有字节序的问题呢?

字节序是什么

首先,需要明白的是,由于各种历史原因,不同的CPU存储的处理一个多字节数据的方式是不一样的:

  • 大端字节序(big endian):高位字节在前,低位字节在后,比如两个字节中:1234 5678 ,大端字节序CPU会处理为一千两百三十四 万 五千六百七十八
  • 小端字节序(little endian):低位字节在前,高位字节在后,同样比如:1234 5678, 小端字节序CPU会处理为五千六百七十八 万 一千两百三十四

其实,需要补充明白的是,虽然有字节序的概念,但是这仅仅是在处理多字节数据才会存在的问题,比如double,long这种一个字节无法存放的数据。字节序并不会影响数据的整体顺序,比如我存放一条文本:我们,并不会因此字节序不同的原因变为们我,对于任何cpu来说,字节序对于用户来说都是透明的,这也是为什么我们常常编程,但是很少会遇到字节序的问题。

为什么会有字节序的问题

有人可能就会说了,为什么非要有字节序的问题,都规定好cpu读取数据的顺序,就不会这么复杂了。确实如此,但是不同的字节序会导致cpu处理数据的性能不同,比如:

  • 对于小端cpu来说,计算加法会更方便,但是对于常用除法的cpu来说,还是大端好
  • 对于小端cpu来说,强制转换数据类型不用调整字节的内容,1,2,4字节的存储方式都一样,但是对于大端来说,符号位的判断为固定第一个字节,更加容易判断正负
  • 。。。

因此,一般来说,x86Z80等处理器一般是小端序,而Motorola 6800等处理器为大端序,还有一类入ARM,PowerPC是可以手动配置的。

怎么避免字节序的问题

前面说过,一般来说字节序的问题对于用户来说,是透明的,对于同一台电脑,同一种语言,是永远不会出现字节序的问题,想要避免字节序的问题,要明白什么时候会因为字节序带来问题:

当两个系统处理的字节序有可能不同的时候

看着像废话,但是道理确实是这样。

比如C/C++语言的字节序是依赖于编译平台所在的CPU,而对于Java来说,是规定使用大端序,而这个时候如果Java系统存储一个多字节数据之后,再使用C++去相同的内存读取,可能就会出现问题。

同理的还有就是常说的网络字节序,因为TCP/IP协议规定socket通过TCP/IP协议传送字节的时候,统一使用大端序,这样对于那些使用小端序的操作系统来说,就需要进行本地字节序和网络字节序相互转换。


这里再回到文章开篇的问题,为什么UTF-16会有大端序,小端序之分,因为UTF-16处理单元为2字节,就好像long,double,而如果不规定大端序和小端序,那么如果一个字符,先通过使用小端序的程序保存,然后再使用其他使用大端序的程序读取,读取的数据可能就会有很大的不同。

而为什么UTF-8没有这个问题呢?最主要的原因是UTF-8处理单位为一个字节。况且UTF-8每个字节都标明了顺序。