/**
 * This file test the endian of your machine:
 * big-endian or little-endian, by visiting
 * the memory sequentially byte by byte of
 * a intendly constructed integer.
 */
 
#include <cstdint>
#include <stdio.h>
#include <iostream>
 
using namespace std;
 
static void print(void* ptr, size_t size)
{
    // convert to char* so we can visit the memory byte by byte
    unsigned char* _ptr = static_cast<unsigned char*>(ptr);
    // print the value of each byte in ptr
    for (size_t i = 0; i < size; ++i)
        cout << static_cast<int>(_ptr[i]);
    cout << endl;
}
 
int main()
{
    uint32_t a = 0x01020304;
    /*
     * if it prints 4321, indicates 低位在前,对应little-endian
     * it it prints 1234, indicates 高位在前,对应big-endian
     */
    print(&a, 4);
    return 0;
}
 
/**
 * Output on my machine
4321
 */

字节序就是计算机存储数据的时候将低位数据存在低位地址还是高位地址。举个例子,数值0x2211使用两个字节储存:高位字节是0x22,低位字节是0x11。

  • 大端字节序:高位字节在前,低位字节在后,这是人类读写数值的方法。
  • 小端字节序:低位字节在前,高位字节在后,即以0x1122形式储存。

如果太多记不住,至少要记住:

  1. 字节序的概念: 读一段内存从低位向高位读(从左往右),先读到高位字节还是低位字节
  2. 符合人类读写数值的方法是大端序(big-endian)

既然如此,我们要判断一台机器是big-endian还是little-endian,只需要构造一端内存,按字节从低位地址向高位地址访问,看看低位地址存的是高位字节,还是低位字节即可。

且看上述代码,构造了一个整数0x01020304,然后通过将首地址转成char*的方式去按字节读取内存中的值(这样做的目的是,char*可以逐字节的读取内存;而int*一次指针移动会移动sizeof(int)个字节)。读出来如果是符合书写习惯的1234, 则表明机器是big-endian, 反之little-endian.

这也是一段内存的两种不同的解释方式,recall that Because all data on a computer is just a sequence of bits, we use a data type (often called a “type” for short) to tell the compiler how to interpret the contents of memory in some meaningful way.

Hint

网络字节序一般是大端。