a man
2026-01-02
点 赞
1
热 度
14
评 论
0

大端序 VS 小端序

  1. 首页
  2. misc
  3. 大端序 VS 小端序

字节序(Endianness)

含义

在计算机系统中,数据是以字节为单位进行存储和访问的。字节序描述的是在一个多字节数据(如 int、float 等)中,各个字节的排列顺序。

大端序(Big Endian)

  • 存储顺序:高位字节存储在内存的低地址处,低位字节存储在高地址处。即高位在前,低位在后
  • 例如:一个 4 字节的整数 0x12345678:
  内存地址:  0x00   0x01   0x02   0x03
  存储内容:  0x12   0x34   0x56   0x78
  • 特点:这种字节序符合人类从左到右的阅读习惯,所以常用于网络协议(也被称为网络字节序 Network Byte Order)和某些文件格式(如 PNG、JPEG 等)。

小端序(Little Endian)

  • 存储顺序:低位字节存储在内存的低地址处,高位字节存储在高地址处。即低位在前,高位在后
  • 例如:一个 4 字节的整数 0x12345678:
  内存地址:  0x00   0x01   0x02   0x03
  存储内容:  0x78   0x56   0x34   0x12
  • 特点:相当于在倒着写。由于小端序更贴近 CPU 的硬件设计逻辑(尤其是在加法、移位操作中),因此 x86x86_64 架构都采用小端序,部分 ARM 处理器支持双端序模式(可切换)。

词源

这个词最早由计算机科学家 Danny Cohen 在 1980 年的论文《On Holy Wars and a Plea for Peace》中提出,灵感来源于乔纳森·斯威夫特的小说《格列佛游记》。

在小说中,小人国的居民因为吃鸡蛋时是先敲大头(Big End)还是先敲小头(Little End)而分裂成两个阵营,引发了战争。

大端序 vs 小端序

Cohen 用这个比喻来形容计算机系统在处理字节顺序时的分歧。大端序和小端序的根本区别就是:在内存低地址处存放的是高位字节(大端序)还是低位字节(小端序)

判断字节序的代码 (C/C++)

#include <iostream>

bool isLittleEndian() {
    int num = 1;
    // 将 int 的地址转换为 char* 指针,读取第一个字节
    char* ptr = reinterpret_cast<char*>(&num);
    // 如果第一个字节是 1,说明是小端序
    return (*ptr == 1);
}

int main() {
    if (isLittleEndian()) {
        std::cout << "当前系统是小端序 (Little Endian)" << std::endl;
    } else {
        std::cout << "当前系统是大端序 (Big Endian)" << std::endl;
    }
    return 0;
}

原理说明

  • 整数 1 的十六进制表示为 0x00000001(32位)
  • 小端序:内存中存储为 01 00 00 00,第一个字节是 0x01
  • 大端序:内存中存储为 00 00 00 01,第一个字节是 0x00

字节序转换函数

在网络编程中,经常需要在主机字节序和网络字节序之间转换:

#include <arpa/inet.h>  // Linux/Unix
// #include <winsock2.h>  // Windows

// 主机字节序 → 网络字节序(大端序)
uint32_t host_val = 0x12345678;
uint32_t net_val = htonl(host_val);  // [h]ost [to] [n]etwork [l]ong
uint16_t net_short = htons(host_val); // [h]ost [to] [n]etwork [s]hort

// 网络字节序 → 主机字节序
uint32_t host_val2 = ntohl(net_val);  // [n]etwork [to] [h]ost [l]ong
uint16_t host_short = ntohs(net_short); // [n]etwork [to] [h]ost [s]hort

比特序(Bit Endianness)

除了字节序,还存在比特序的概念。

什么是比特序?

比特序描述的是在一个字节内部,各个比特位的排列顺序。

  • MSB(Most Significant Bit First):最高有效位在前,类似大端序
  • LSB(Least Significant Bit First):最低有效位在前,类似小端序

比特序的应用场景

  1. 串行通信协议:如 UARTSPII2C 等,需要规定比特的传输顺序
  2. 位操作和位域:在某些嵌入式系统或网络协议中,需要精确控制比特顺序
  3. 硬件寄存器:不同芯片厂商对寄存器的比特编号方式可能不同

示例:位域的比特序问题

struct BitField {
    unsigned int a : 1;  // 占 1 位
    unsigned int b : 2;  // 占 2 位
    unsigned int c : 5;  // 占 5 位
};

在不同的编译器和架构下,这些位域在字节中的排列顺序可能不同,这就是比特序的影响。

注意:C/C++ 标准并未规定位域的内存布局,因此在跨平台或底层硬件编程时需特别小心。

实际应用中的注意事项

1. 网络编程

  • TCP/IP 协议栈使用大端序(网络字节序)
  • 发送数据前需要将主机字节序转换为网络字节序
  • 接收数据后需要将网络字节序转换为主机字节序

2. 文件格式

  • 某些文件格式(如 PNGJPEG)使用大端序
  • 某些文件格式(如 BMPGIF)使用小端序
  • 读写文件时需要注意字节序转换

3. 跨平台开发

  • 不同架构的机器可能使用不同的字节序
  • 数据交换时必须明确约定字节序
  • 可以使用序列化库(如 Protocol BuffersMessagePack)来自动处理字节序问题

4. 性能考虑

  • 字节序转换本身有性能开销
  • 在高性能场景下,尽量减少不必要的转换
  • 某些 CPU 提供专门的字节序转换指令(如 x86 的 bswap

总结

对比项大端序小端序
存储方式高位在前,低位在后低位在前,高位在后
可读性符合人类阅读习惯不太直观
应用场景网络协议、部分文件格式x86/x64 CPU、大多数嵌入式系统
硬件效率一般更高(便于加法、移位等操作)

核心要点

  • 字节序只影响多字节数据的存储顺序
  • 单字节数据(如 char)不受字节序影响(宽字符wchar是受影响的)
  • 网络传输统一使用大端序
  • 比特序在特定场景(串行通信、硬件寄存器)中需要关注
  • 跨平台开发时要注意字节序转换

我行走在现实与幻想的交界线,左手是被岁月磨钝的理性,右手却仍紧握着不肯熄灭的狂想。世界在我眼中不过是一盘尚未解完的棋局,而我早已越界成子,亦是执棋之人。

a man

enfj 主人公

站长

具有版权性

请您在转载、复制时注明本文 作者、链接及内容来源信息。 若涉及转载第三方内容,还需一同注明。

具有时效性

文章目录

欢迎来到云游记

7 文章数
4 分类数
1 评论数
5标签数
最近评论