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

目录

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

简介

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

  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