从剥鸡蛋皮说起的大端法和小端法 | 一分钟系列

用户角度的内存

对于我们这些码农来说,内存相当于由若干个连续的格子组成,画个图就是这样:

如图所示的内存结构一共由 n 个连续的格子组成,每个格子可以存储一个字节的数据(1字节 = 8个位)。 每个格子都有它唯一的编号,称之为 内存地址 那么:

  • 如果我们的计算机是32位的话,理论上可以访问的内存格子个数就是2³²(也就是4GB),相应的内存地址范围就是: 0 ~ 2³² - 1

  • 如果我们的计算机是64位的话,理论上可以访问的内存格子个数就是2⁶⁴(这是一个很大很大的数),相应的内存地址范围就是: 0 ~ 2⁶⁴ - 1

字节的权重

我们知道计算机中使用二进制来表示数据,不过二进制对人类来说太不友好,将它们转换成十六进制来看更舒服一些,比方说对于下边这个由4个字节组成的二进制数据(字节之间没有空格,只是为大家看起来美观我才加了空格):

二进制字节 00010010 可以被转换成十六进制 0x12 ,二进制字节 00110100 可以被转换成十六进制 0x34 ,二进制字节 01010110 可以被转换成十六进制 0x56 ,二进制字节 01111000 可以被转换成十六进制 0x78 所以整个数字转为十六进制数据就是:

0x12345678

其中:

  • 字节 0x12 在左边,代表着 1 × 16⁷ + 2 × 16⁶ ,这个 0x12 字节占的权重比较大。

  • 字节 0x34 代表着 3 × 16⁵ + 4 × 16⁴ ,这个字节占的权重其次。

  • 接着是字节 0x56 ,代表着 5 × 16³ + 6 × 16² ,这个字节占的权重再次。

  • 最后是字节 0x78 ,代表着 7 × 16¹ + 8 × 16⁰ ,这个 0x78 字节占的权重是最小的。

高级语言的类型

我们一般是使用高级语言来编程的(区别于机器语言或者汇编语言),高级语言里有一种 类型 的概念,有的类型的数据要占用连续的几个内存格子。 比方说某种语言里有一种称之为 int 的类型,该类型需要占用4个字节的大小。 如果说我们想在高级语言里将下边的这个数(十六进制)设置成 int 类型:

0x12345678

那这个数据该以怎样的方式塞到内存格子中呢? 是该把高权重的字节放到低地址中,还是把高权重的字节放到高地址中呢? 这其实和我们吃鸡蛋时应该先从大头剥鸡蛋皮还是先从小头剥鸡蛋皮更好一点的问题差不多,其实没啥不一样。 不过最开始设计计算机的大叔们由于事先没商量好,造成了这样的后果:

  • 有的人把高权重的字节放到了低地址中,人们把这样表示多字节数据的方式称之为 大端法

  • 有的人把高权重的字节放到了高地址中,人们把这样表示多字节数据的方式称之为 小端法

由于最初大家没有商量好,导致对于多字节数据在不同的机器上采用不同的表示方法,这对于程序的可移植性造成了影响。 另外,现代社会中网络成了不可或缺的一部分,当将某个多字节数据从一个使用大端法表示的机器中发送到一个使用小端法表示的机器中时,便会造成错误,于是设计网络的大叔规定,数据在网络上进行传输时,必须统一采用大端法进行传输,那么对于使用小端法的机器而言,就得多费一茬手续,再转一下呗~