字节顺序--大端存储和小端存储

目录

从哪一端(大端还是小端)打开半熟的鸡蛋?

简介

对于多字节的数据,必须搞清楚两个问题:

  1. 地址是什么
  2. 在存储器中如何排列字节

第一个问题,存储器大都一样,将多字节数据存放在连续的地址中,将所用字节中最小的地址作为数据的地址。但第二个问题却分成两派:大端派 (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