字节序
字节序(Byte Order),指的是多字节数据类型,在内存中存储的顺序。
计算机系统,采用字节作为逻辑寻址单位。在处理多字节数据类型时,就要区分字节序。
Big-Endian、Little-Endian
- Big-Endian 大端(高位字节在前)
低位字节存放在内存的高地址端,高位字节存放在内存的低地址端。
低地址存放最高有效位(MSB)
- Little-Endian 小端(低位字节在前)
低位字节存放在内存的低地址端,高位字节存放在内存的高地址端。
低地址存放最低有效位(LSB)
说明
- 大端小端的概念,是面向多字节数据类型的内存存储方式定义的,比如2字节、4字节、8字节的整型、长整型、浮点型等,单字节没有字节序的问题。
- “前” 是指靠近内存低地址(起始地址),存储在硬盘上就是先写那个字节。
- 内存地址生长方向为: 从前(左)到后(右),由低地址到高地址 (这是不变的)。
- 大端直观,因为与现实生活中,数字书写形式一致: 从前(左)到后(右),由高位到低位。
小端符合人的思维,低位值小,就应该放在内存地址小的地方,高位值大就应该放在内存地址大的地方。
举个栗子
1 |
|
MSB、LSB
- 最高有效位 MSB: Most Significant Bit
最高有效位(MSB),有时候叫做最左边的位,是在一个n位二进制数字中的n-1位,这个位有最高的权重(2^(n-1))。第一个或最左边的位,当这个数字被用一般的方式书写时。
- 最低有效位 LSB: Least Significant Bit
最低有效位(LSB)是给这些单元值的一个二进制整数位位置,就是,决定是否这个数字是偶数或奇数。LSB有时候是指最右边的位,因为写较不重要的数字到右边位置符号的协定。它类似于一个十进制整数的最不重要的数字,它是在一个(最右边)位置的数字。
HBO、NBO
主机字节序
主机字节序(HBO,Host Byte Order),就是上文介绍的,多字节数据类型,在内存中存储的顺序。
其它详见上文。
不同的机器 HBO 不相同,与 CPU 设计有关:
Intel x86,采用小端字节序
IBM PowerPC,采用大端字节序
网络字节序
网络字节序(NBO,Network Byte Order),是网络传输时的字节序。
网络传输的数据,是字节流。
对一个多字节数据来说,在进行网络传输的时候,发送方先传递高位字节还是低位字节?
接收方收到第一个字节的时候,它将这个字节作为高位字节还是低位字节处理?
它是 TCP/IP 协议中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,保证了数据在不同主机之间传输时能够被正确读取。
网络字节序,采用 Big-Endian 大端字节序,也就是高位字节先走。
以 4 字节整数为例: 0x12345678,先发送 12,再依次发送 34,56,78。
Java 字节序
C/C++ 语言编写的程序里,字节序是跟编译平台所在的 CPU 相关。
Java 是平台无关的,JVM 为我们屏蔽了大量的底层细节和复杂性。
Java 默认字节序,是 大端字节序。
示例
1 | public final class ByteOrderTest { |
ByteBuffer
1 | public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer> { |
ByteOrder
1 | public final class ByteOrder { |
Bits
1 | /** |
附: 词源
Endian 这个词,来源于 Jonathan Swift 在 1726 年写的讽刺小说 “Gulliver’s Travels”(《格利佛游记》)。
小说描述了 Gulliver 畅游小人国时,碰到了如下的一个场景。
小人国里的小人,因为非常小(身高6英寸),所以总是碰到一些意想不到的问题。
有一次因为对水煮蛋该从大的一端(Big-End)剥开,还是小的一端(Little-End)剥开,引发了一场战争,并形成了两支截然对立的队伍。
支持从 Big-End 剥开的人,Swift 就称作 Big-Endians,支持从 Little-End 剥开的人,就称作 Little-Endians(后缀 ian 表明的就是支持某种观点的人:-)。
Endian这个词由此而来。
Danny Cohen 一位网络协议的开创者,第一次使用这两个术语指代字节序,后来就被大家广泛接受。
参考
本文参考了互联网上大家的分享,就不一一列举,在此一并谢过。
也希望本文,能对大家有所帮助,若有错误,还请谅解、指正。