0%

union 应用之检测 CPU 的 Endian

Little endianBig endian 是 CPU 存放数据的两种不同方式。

对于整型、长整型等数据类型:

  1. Big endian :认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节);
  2. Little endian :认为第一个字节是最低位字节(按照从低地址到高地址的顺序存放数据的低位字节到高位字节)。

例如,假设从内存地址0x0000 开始有以下数据:0x12, 0x34, 0xab, 0xcd

Endian 0x0000 0x0001 0x0002 0x0003
big-endian 0x12 0x34 0xab 0xcd
little-endian 0xcd 0xab 0x34 0x12

问题:如何判断系统中的 CPU 是 Little endian 还是 Big endian 模式?(假设机器为:32 位

解答:将一个字节的数据和一个整型数据存放于同样的内存始地址,通过读取整型数据,分析数据在整型数据的高位还是低位来判断 CPU 是 Little endian 还是 Big endian 模式。

  1. 例码1:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    typedef enum __endianType {
    Endian_little,
    Endian_big,
    }EndianType;

    EndianType CheckEndian1()
    {
    typedef unsigned char BYTE;

    unsigned int num, *p_num;
    p_num = #
    num = 0; // 设置 num 占用的所有字节内容都为:0x00
    *(BYTE *)p_num = 0xff; // 通过指针类型强制转换并对整型数据《首字节》赋值,判断该赋值赋给了高位还是低位

    if(0xff == num)
    {
    return Endian_little;
    }
    else // 0xff000000 == num
    {
    return Endian_big;
    }
    }
  2. 例码2:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    typedef enum __endianType {
    Endian_little,
    Endian_big,
    }EndianType;

    EndianType CheckEndian2()
    {
    union {
    unsigned int a;
    char c;
    }endianUnion;

    endianUnion.a = 1;

    if (1 == endianUnion.c)
    {
    return Endian_little;
    }
    else
    {
    return Endian_big;
    }
    }
  3. 例码3:(Linux 内核的实现方式)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    typedef enum __endianType {
    Endian_little,
    Endian_big,
    }EndianType;

    EndianType CheckEndian3()
    {
    union {
    char c[4];
    unsigned int num;
    } endianUnion = {'l', '?', '?', 'b'};

    if ('l' == (char)endianUnion.num) // 取首字节判断
    {
    return Endian_little;
    }
    else // 'b' == (char)endianUnion.num
    {
    return Endian_big;
    }
    }