如果两个人收到同一封信,一个人从左往右读,另一个人从右往左读,会发生什么?在计算机世界里,确实会发生类似的事情。因为不同的计算机把多字节数字存放到内存中的顺序并不相同,而指代这种顺序的词,正是“字节序(Endianness)”。
字节序,简单来说就是“由多个字节组成的值在存入内存或传输时,先放哪一端字节的顺序”。这个名字来自乔纳森·斯威夫特(Jonathan Swift)1726年的小说《格列佛游记》(Gulliver’s Travels)。小说中,利立浦特和不来夫斯古的人们为了煮鸡蛋该从大头(big end)还是小头(little end)敲开而不惜开战。1980年,计算机科学家丹尼·科恩(Danny Cohen)在文章《论圣战,并呼吁和平》(On Holy Wars and a Plea for Peace)中,把字节顺序之争比作这场鸡蛋战争,使“大端序”“小端序”这两个说法流传开来。
本文将依次介绍字节序产生的原因、大端序与小端序的区别、字节序不同的计算机相遇时出现的问题,以及如今处理字节序的方法。
鸡蛋该从哪头敲开:字节序
1. 字节序为什么会出现

计算机内存以字节(8位)为单位编排地址。然而一个整数通常要占用2字节、4字节、8字节等多个字节。因此,把一个值分到多个格子里存放时,就必须决定先放哪个字节。
(1) 以字节为单位的地址
内存的每个格子都有一个地址,如0、1、2……,每个格子只能放1字节。要存放一个4字节整数,就需要连续的四个格子。
(2) 高位与低位
在十六进制数0x12345678中,12是负责最高位的最高有效字节,78是负责最低位的最低有效字节。这四个字节从低地址开始按什么顺序摆放,就是字节序。
(3) 没有标准答案的选择
无论哪种顺序,只要在一台计算机内部始终如一地使用,计算结果都是一样的。因此早期的计算机公司各自选择了对自己设计有利的一种,这种差异一直延续到今天。
2. 大端序与小端序的区别

假设把0x12345678存放在从地址100开始的四个格子里。大端序从100号开始按12、34、56、78的顺序存放,小端序则反过来,按78、56、34、12的顺序存放。

- 大端序(Big-endian):把最高有效字节放在最低地址的方式,与人们书写数字的顺序相同。
- 小端序(Little-endian):把最低有效字节放在最低地址的方式,英特尔x86系列处理器采用这种方式。
- 双端序(Bi-endian):同时支持两种方式的设计,ARM和PowerPC等属于此类。
- 最高有效字节(Most Significant Byte):在一个值中负责最高位的字节,也常缩写为MSB。
(1) 大端序的优点
从前往后直接查看内存内容时,数字的顺序与书写顺序一致,便于人们检查。IBM大型机和摩托罗拉68000等处理器采用了这种方式。
(2) 小端序的优点
由于低位位于低地址,从同一地址按1字节、2字节或4字节读取时,值的低位部分都能对得上。对于从低位开始计算进位的加法来说也很自然。
(3) 与位序无关
字节序通常指字节的摆放顺序。由于处理器把一个字节当作一个整体来处理,一个字节内部的位序在程序中几乎不需要关心。
3. 字节序不同的计算机相遇时

在一台计算机内部,字节序几乎不会显现出来。问题出在通过文件或网络把数据交给字节序不同的计算机时。
(1) 被反着读的数字
小端序计算机用4字节存放整数1时,会变成01 00 00 00。如果大端序计算机原样读取这些字节,就会得到0x01000000,也就是16,777,216这个莫名其妙的值。
(2) NUXI问题
把以16位为单位采用小端序的PDP-11上的数据搬到采用另一种方式的机器上时,曾出现“UNIX”被读成“NUXI”的情况。这是每两个字节互换了位置造成的,这个名字后来成了字节顺序问题的别称。
(3) 难以发现的错误
同型号机器之间测试时一切正常,只有与不同型号连接时数值才会出错,因此往往要花很长时间才能找到原因。
4. 如今处理字节序的方法

既然无法消除字节序的差异,开发者便通过事先约定交换数据时的顺序来解决问题。
(1) 网络字节序
互联网协议(TCP/IP)把大端序定为标准顺序。因此在C语言等环境中,会用htonl(host to network long)、ntohl等函数在发送前和接收后转换顺序。
(2) 由格式规定的顺序
Java类文件规定使用大端序;字符编码UTF-16则在最前面加上字节顺序标记(BOM),FE FF表示大端序,FF FE表示小端序。
(3) 小端序占优
随着x86和大多数ARM设备以小端序运行,如今的个人电脑和智能手机实际上以小端序为主流。不过,网络和许多文件格式中仍保留着大端序,因此转换依然必不可少。
就像鸡蛋无论从哪头敲开味道都一样,字节序也不是哪一方对错的问题,而是彼此对齐约定的问题。在传递数据之前先把顺序定好,这个简单的想法,正是理解字节序的第一步。