巧记大小端字节序

0. 一句话总结

从左向右读(从低地址到高地址),
先遇到权重“大”的就是“大”端字节序,
先遇到权重“小”的就是“小”端字节序。

1. 详细解释

计算机存储的最小单位是比特(bit),一个比特只有0和1两种状态。相邻的8个比特构成一个字节(byte)。字节通常是程序可以寻址的最小单元,每个字节都有各自独立的地址,相邻字节的地址逐个递增。
每个字节由8个比特组成,所以共有2的8次方(即256)种状态。常用16进制来表示一个字节的值:前后4个比特分别为一组,每组比特可能的取值有16个:0~9以及A~F。所以16进制下,一个字节是用两个数字表示的
下面我们只考虑计算机存储数字的情况。一个字节的存储范围是非常有限的(有符号数0到255,无符号数-128到127),超过这个范围的数字就要用多个连续的字节表示。这里就出现了字节顺序的问题:到底是把高位字节放在高地址,低位字节放在低地址,还是反过来呢?比如0x12345678需要占用4个字节,那就有两种可能的存储顺序:

two_storage_style.png

注意:0x12是一个字节,作为一个整体,无论使用哪种方式,1和2的顺序是不会变的,也就是说不会存储成0x21。
对于具体采用哪种存储顺序,人们并没有形成统一的标准,所以就有了两种字节序:大端字节序和小端字节序。大端字节序是高位字节放在低地址,低位字节放在高地址。小端字节序是高位字节放在高地址,低位字节放在低地址。如下图所示:

big_little_endian_demo.png

可以通过下面的方式记忆:
从左向右读(从低地址到高地址),
先遇到权重“大”的就是“大”端字节序,
先遇到权重“小”的就是“小”端字节序。

2. 哪些数据类型需要考虑字节序?

很明显,只有超过一个字节的数据类型才需要考虑字节序。但这并不是完全准确的:举例来说,C语言的结构体也是一个多字节的数据,但它的成员在内存中的顺序就是代码中的顺序,与当前是哪种字节序无关。所以我认为应该在“多字节数据”的基础上再加上一个限制:“通常是基本数据类型(例如uint32_t)”。

3. 什么时候需要关注字节序?

只有当读数据和写数据时有可能使用不同的字节序时,才需要关注字节序。例如跨平台文件、网络传输等。

4. 怎样判断当前的字节序?

可借助C语言中的联合体或对数据进行强制类型转换的方式得知当前机器的字节序。可参考:https://github.com/CoderNotCold/endian-c

5. 常见字节序

5.1 网络字节序

大端字节序

5.2 Java的字节序

大端字节序

5.3 部分CPU的字节序

x86:小端字节序
ARM:指令只能是小端字节序,数据的大小端模式是可切换的:默认为小端字节序,可通过汇编指令SETEND切换数据的大小端模式,例如SETEND BE切换为大端字节序,SETEND LE切换为小端字节序。ARM CPU内部是使用CPSR的E比特位表示大小端字节序的,SETEND修改也就是该比特位。

你可能感兴趣的:(巧记大小端字节序)