字节序 — 大端序与小端序

字节序

字节序(Endian/Byte Order)表示多字节数据的存储规则。字节序分为两种:

  • 小端序(Little Endian): 低地址端存储低位字节,高地址端存储高位字节
  • 大端序(Big Endian): 低地址端存储高位字节,高地址端存储低位字节
网络传输一般采用大端序,因此我们将大端序也称作网络字节序。对于单个字节的数据,没有字节序的问题。但对于多字节的数据来说,当我们存储或读取这类数据时,往往要面对字节序的问题。

例如,对于 int 型整数 0x01020304 来说,按照小端序存储,在内存中的顺序(从低到高)如下:

04030201
按照大端序存储,在内存中的顺序(从低到高)如下:
01020304

采用哪种字节序?

大端和小端有其各自的优势。大端存储的第一个字节是高位,对于一些数值判断(比如正负)会很迅速;小端存储的第一个字节是低位,符号位在最后一个字节,从低位开始计算,效率比较高。

采用哪种字节序是由硬件厂商决定的,例如我们常用的 x86(包括x86_64)架构的 CPU 采用的是小端序。

下面通过程序验证 CPU 采用的何种字节序:

@SuppressWarnings("restriction")
public class ByteOrder {
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        Unsafe unsafe = (Unsafe) field.get(null);
        long a = unsafe.allocateMemory(8);
        try {
            unsafe.putLong(a, 0x0102030405060708L);
            byte b = unsafe.getByte(a);
            switch (b) {
                case 0x01:
                    System.out.println("大端序");
                    break;
                case 0x08:
                    System.out.println("小端序");
                    break;
                default:
                    assert false;
            }
        } finally {
            unsafe.freeMemory(a);
        }
    }
}

输出结果:

小端序

可以看出,电脑的 CPU 采用的是小端序。

注意,程序中用的是 sun.misc.Unsafe 类,这个类是非公有API,Oracle 公司已经不提供它的源码了,但我们可以下载 OpenJDK 源码来查看。这里是通过反射的方式获取 Unsafe 对象(参考:sun.misc.Unsafe的理解)。如果在 Eclipse 中运行的话,还需要设置允许使用限制API。

更简单的是采用 Java 自带的方法输出字节序,如下所示:

System.out.println(ByteOrder.nativeOrder());

JVM字节序

JVM规范规定了 Class 文件采用大端字节序。Java标准库所支持的序列化格式,跟 Class 文件一样,也是规定用大端方式存储多字节数据。这就使得在 x86 上用 Java 自带的序列化/反序列化功能也要经过大小端转换(参考:在 x86 上的 JVM 大小端转换有多少性能开销?)。


什么时候需要转换字节序?

虽然大小端的问题在内存、软件等地方存在,但在下面两种情况下不需要关注这个问题:

  • 在单机上,使用同一种编程语言,读写变量或文件、进行网络通信
  • 在分布式场景下,使用同一种编程语言,在大小端模式相同的机器之间传输信息

当不符合上面条件时,比如通过 Java 向一个 C++ 服务器发送信息,就需要处理字节序的问题。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值