字节顺序--大端存储和小端存储
目录
从哪一端(大端还是小端)打开半熟的鸡蛋?
简介
对于多字节的数据,必须搞清楚两个问题:
- 地址是什么
- 在存储器中如何排列字节
第一个问题,存储器大都一样,将多字节数据存放在连续的地址中,将所用字节中最小的地址作为数据的地址。但第二个问题却分成两派:大端派 (big endian) 和小端派 (little endian)。
大小端指的数据在连续地址中的排序方式,大端将从数据最高有效字节开始存放,小端从数据最低有效字节开始存放。
打个比方,存放数据 0x1234
需要四个字节,大端将最高字节 1
放在最小地址,小端将最低字节 4
放在最小地址。
举一个详细的例子说明上述问题。
在 32 位机器中存放 int 型整数 19088743
(=0x01234567
),需要四个字节,起始地址在 0x10
,地址范围为 0x10-0x13
。
大端法:
小端法
大小端检测
C 检测大小端的程序
来自 stackoverflow 的问题回复 《Detecting endianness programmatically in a C++ program》
int is_big_endian(void)
{
union {
uint32_t i;
char c[4];
} bint = {0x01020304};
return bint.c[0] == 1;
}
回答人说使用 union
比使用指针转换好,不会有警告。
测试程序
测试程序1
#include <iostream>
using namespace std;
int is_big_endian(void)
{
union {
uint32_t i;
char c[4];
} bint = {0x01020304};
return bint.c[0] == 1;
}
int main()
{
cout<<is_big_endian()<<endl;
return 0;
}
测试结果
AIX PowerPC_POWER7
输出 1
,大端
SUSE Intel(R) Xeon(R) CPU E7- 8850
输出 0
,小端
测试程序2
#include <iostream>
#include <cstdio>
using namespace std;
void show_endian(void)
{
union {
uint32_t i;
char c[4];
} bint = {0x01234567};
printf("address: %#x %#x %#x %#x\n",&bint.c[0],&bint.c[1],&bint.c[2],&bint.c[3]);
printf("value: %10x %10x %10x %10x\n", bint.c[0], bint.c[1], bint.c[2], bint.c[3]);
}
int main()
{
show_endian();
return 0;
}
运行结果:
AIX PowerPC
address: 0xfffff1d0 0xfffff1d1 0xfffff1d2 0xfffff1d3
value: 1 23 45 67
Linux Intel
address: 0x240dcb40 0x240dcb41 0x240dcb42 0x240dcb43
value: 67 45 23 1