iGBlog

iGuan7u

iOS 出身的小伙子,对 Objective-C、Swift、以及 Javascript 有浓厚的兴趣。热衷使用原生实现所有功能,厌恶一切的跨平台开发技术。喜欢分享工作过程中遇到的问题以及日常工作中遇到的新技术。希望这个博客能给你带来一点启发。

大端与小端

起源

众所周知,计算机只存储 0/1 数据,任何自然世界中表达的信息,到达计算机层面,都会变成 0/1 表示并保存起来,而一个 0/1 的数据单元,我们称之为比特 (bit)。而在最初的计算机发展中,为了表示 0-9 的数据,以及最基本的运算符号,4 bit 便足以存储。随后当计算机需要存储 26 个英文字母,便发展到了需要 8 bit 作为一个存储单元,这就是计算机基础的编码标准 —— ACSII 编码标准。同时设定了 1 个 ACSII 编码存储单元为 1 个字节 (byte)。
然而,1 个 byte 显然不足以存储自然世界中的信息。那么,如果有序地组织 bytes 进行存储便引出了这篇文章的背景。

发展

Lilliput 和 Blefuscu 这两个强国在过去的 36 个月中一直在苦战。战争的原因:大家都知道,吃鸡蛋的时候,原始的方法是打破鸡蛋较大的一端,可是那时皇帝的祖父由于小时候吃鸡蛋按这种方法把手指弄破了,因此他的父亲就下令,命令所有的子民吃鸡蛋必须先打破鸡蛋较小的一端,违令者重罚。然而老百姓对此法令极为反感,期间发生了多次叛乱,最终一个皇帝因此送命,而另一个丢了王位。
——《格利佛游记》乔纳森·斯威夫特(Gulliver’s Travels by Jonathan Swift)

在游记中,斗争两排以 Big Endian 和 Little Endian 自称 (-ian 尾缀表示人) 。一位网络协议开创者 Danny Cohen 则首次将这个称呼引入计算机世界,并将其推广出去,中文翻译:大端小端
在计算机系统中,所有的信息都是有序地存储着的,其中每一个存储单元都有一个唯一的位置编码,称之为内存地址。而大小端的差别,就是根据内存地址存放方式的差别。

大端

高位字节排放在内存低的地址端,低位字节排放在内存高的地址端。

小端模式

低位字节排放在低的内存地址端,高位字节排放在高低内存地址端。

下图表示 12345678 数字在内存中的表现差异:

bigLittleEndian.gif

上图中展示的,方框中数字为存储的内容,方框下数字为该存储对应的地址。可以从图中了解到,大端模式是低内存地址保存实际数字高位的部分,而小端模式则是相反,低内存地址保存的是实际数字高位的部分。如果计算机知识比较薄弱的读者,可能会好奇怎么会用小端模式如此奇怪的方式去保存数据呢,大端模式看起来明显可读性更高。

原因

存在即有意义。

小端模式虽然明显有别于人类的正常理解,可是这么多年发展以来,小端模式能一直被人们所使用,必然有其必要性的:
小端模式更符合计算运行规律。基本计算都有个铁则:从低位算起。小端模式的优势可以从这里看出。举例说,两个数相加,需要从个位开始逐位相加,个位相加产生的进位数需要带到十位进行继续进行运算。小端模式在内存低位即可获取到个位的数值,十位数值则可以直接从下一个内存地址中获取。所以,数字运算能直接从低位地址一直遍历至最高位地址即可。其次,计算机根本不关心可读性。计算机不同于人类,只要存在固定的逻辑(不需要是否合理),计算机都能正常识别跟运行。因此,小端模式长久以来都被广泛采用。
相反,在大端模式下进行数值相加,在获取到数值内存地址后,还需要根据占用内存空间的长度,计算出该数值所占用内存地址最高位的空间,然后逐层往低位递归运算,运算效率就稍微低于小端模式了。
而大端模式下,除了上文提到的便于人们直观认知以外,计算机也容易获取该数值是正数还是负数(首位 0/1 表示该数值为正数或者负数)。

出现场景

搜索显示,小端模式一般出现于操作系统上(笔者认为可能跟上文提到的运算效率有关);大端模式出现在通讯协议中(笔者认为可能方便人类直观调试网络通讯内容)。