Little endian 和 Big endian 是 CPU 存放数据的两种不同方式。
对于整型、长整型等数据类型:
- Big endian :认为第一个字节是
最高位字节
(按照从低地址到高地址的顺序存放数据的高位字节到低位字节); - 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23typedef 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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23typedef 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:(Linux 内核的实现方式)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21typedef 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;
}
}