大小端(Endianness)描述的是多字节数据在内存中的存储顺序。

一、什么是大端与小端

以 32 位整型数 0x12345678 为例(每个十六进制字符占 4 bit,两个字符一个字节):

  • 大端(Big Endian):高位字节存放在低地址,低位字节存放在高地址

    地址:  0x00  0x01  0x02  0x03
    内容:  0x12  0x34  0x56  0x78
    
  • 小端(Little Endian):低位字节存放在低地址,高位字节存放在高地址

    地址:  0x00  0x01  0x02  0x03
    内容:  0x78  0x56  0x34  0x12
    

二、什么时候区分大小端,什么时候不区分

需要区分大小端的场景

  1. 网络通信

    • 网络协议如 TCP/IP 采用 大端序(又称网络字节序),不同主机交换数据时若字节序不同,必须进行转换(如 htonshtonl)。
  2. 跨平台文件存储

    • 比如 BMP、WAV、TIFF 等格式会规定字段字节序,加载文件时需按格式解析。
  3. 嵌入式开发 / 裸机通信

    • MCU、DSP、SoC 通常硬件架构不一致,需统一字节序通信。
  4. 二进制协议解析

    • 自定义通信协议、序列化格式(如 Protobuf)需明确字节序。

不区分大小端的场景

  1. 单机应用层开发

    • 对字节序不敏感,比如纯数学计算、用户界面。
  2. 文本数据处理

    • 文本(如 JSON、XML)按字符序列处理,不涉及多字节合成。
  3. 高层语言内建类型操作

    • 使用 int, float 等类型而不做底层转换时。

三、大小端的应用场景

小端应用(Little Endian)

  • x86/x86_64 架构:几乎所有 PC 和服务器平台默认使用小端。
  • ARM 架构(默认小端):但支持配置成大端(如网络处理器)。
  • Linux、Windows 系统:普遍使用小端格式。
  • LLVM/GCC 编译器:编译默认生成小端指令流。

大端应用(Big Endian)

  • 网络协议:TCP/IP 协议族默认大端(即网络字节序)。
  • 某些嵌入式设备:如部分 PowerPC 架构或旧 MIPS 平台。
  • 标准二进制文件格式:如 Java class 文件、某些音频/图像格式。

四、如何判断机器是大端还是小端

C语言方法(通用)

#include <stdio.h>

int main() {
    unsigned int x = 0x12345678;
    char *p = (char*)&x;
    if (*p == 0x78) {
        printf("Little Endian\n");
    } else if (*p == 0x12) {
        printf("Big Endian\n");
    } else {
        printf("Unknown Endianness\n");
    }
    return 0;
}

使用联合体判断(更直观)

union {
    int i;
    char c;
} endian_test = {0x01000000};

#define IS_BIG_ENDIAN (endian_test.c == 1)

Python 方法

import sys
print(sys.byteorder)  # 输出 'little' 或 'big'

GCC 内置宏

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    printf("Little Endian\n");
#else
    printf("Big Endian\n");
#endif

大端和小端只是字节在内存中的排列方式,不影响数值本身的逻辑意义。