1、 到底什么是大小端呢?

首先我们需要知道,数据是可以存放在内存中的。在计算机系统中,内存的最小存放单元是字节,即一个地址对应一个字节,可以保存一个字节(8Bit)的数据,但是在计算机系统中又不可能全部都是一个字节的存储方式,还有一些8位、16位、32位的系统,它们还会有2个字节、4个字节的变量。所以就有了数据在内存中存放顺序的说法,也就是大小端的由来。

下面举个例子说明一下大小端的原理。

比如现在有一个由2个字节组成的16位整数0x1234,那么它在内存中存放的方式就有:

(1) 将高字节0x12存放在高地址的位置,而将低字节0x34存放在低地址的位置;

(2) 将高字节0x12存放在低地址的位置,而将低字节0x34存放在高地址的位置;

(1)、(2)的演示如下图所示:

image.png

在上图中,(1)的存放方式就是小端,(2)的存放方式就是大端。


再比如,现有一32位int型数0x12345678,假设其MSB(Most Significant Byte,最高有效字节)为0x12,其LSB (Least Significant Byte,最低有效字节)为0x78,在CPU内存中有两种存放方式,如下:

image.png



综上所述,总而言之:
大端:是高字节数据存放到内存的低地址,低字节数据存放在内存的高地址;
  • 小端:是高字节数据存放到内存的高地址,低字节数据存放在内存的低地址;
  • 复制代码


    2、如何确定CPU的大小端模式?

    当我们在写代码的时候,不知道当前环境是用大端模式还是小端模式时,有时候我们使用一些数据结构的时候,在赋值的时候就会导致赋值出错,所以需要检测当前系统的大小端,方便我们写代码的时候安排数据结构的写法。

    对于大小端的判断,当你知道了大小端的原理之后,其实就很简单去验证了,写个代码段就可以测试出来。

    我个人觉得判断大小端最简单的办法是利用共用体的共享内存空间的机制进行判断,另外用指针也是很方便的,这两者大同小异,分别如下:


    (1)使用共用体
    typedef union
  • {
  •         int a;
  •         char b;
  • }test;
  • // 给a赋值
  • test.a = 0x12345678
  • // 判断b的值
  • print(test.b) // 如果test.b=0x12说明是大端,如果test.b=0x78说明是小端
  • 复制代码


    (2)使用指针的方式
    int a = 0x12345678;
  • char *b = (char *)(&a);                // 指针方式其实和共用体的本质很像
  • if(0x78 == *b)
  •     小端模式;
  • else if(0x12 == *b)
  •     大端模式;
  • 复制代码