002_大端和小端的区别

一、大小端出现原因

       计算机系统是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但对于位数大于8位的处理器,如16位或32位/64位的处理器,由于寄存器宽度大于一个字节,那么必然存在一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式的出现。

二、为什么会有小端字节序?

答案是,计算机电路先处理低位字节,效率比较高,因为计算都是从低位开始的。所以,计算机的内部处理都是小端字节序。

但是,人类还是习惯读写大端字节序。所以,除了计算机的内部处理,其他的场合几乎都是大端字节序,比如网络传输和文件储存。

三、

计算机硬件有两种储存数据的方式:大端字节序(big endian)和小端字节序(little endian)。

举例来说,数值0x2211使用两个字节储存:高位字节是0x22,低位字节是0x11

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

32位整数的求值公式也是一样的。


/* 大端字节序 */
i = (data[3]<<0) | (data[2]<<8) | (data[1]<<16) | (data[0]<<24);

/* 小端字节序 */
i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);

四、

同理,0x1234567的大端字节序和小端字节序的写法如下图

 五、

对于整型、长整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节);而 Little endian 则相反,它认为第一个字节是最低位字节(按照从低地址到高地址的顺序存放据的低位字节到高位字节)。

例如,假设从内存地址 0x0000 开始有以下数据: 
0x0000         0x0001       0x0002       0x0003 
0x12            0x34           0xab           0xcd
如果我们去读取一个地址为 0x0000 的四个字节变量,若字节序为big-endian,则读出结果为0x1234abcd;若字节序为little-endian,则读出结果为0xcdab3412。

如果我们将0x1234abcd 写入到以 0x0000 开始的内存中,则Little endian 和 Big endian 模式的存放结果如下: 
地址           0x0000         0x0001        0x0002          0x0003
big-endian   0x12           0x34            0xab            0xcd 
little-endian  0xcd           0xab            0x34            0x12

一般来说,x86 系列 CPU 都是 little-endian 的字节序,PowerPC 通常是 big-endian,网络字节顺序也是 big-endian还有的CPU 能通过跳线来设置 CPU 工作于 Little endian 还是 Big endian 模式。

对于0x12345678的存储:

小端模式:(从低字节到高字节)
地位地址 0x78 0x56 0x34 0x12 高位地址

大端模式:(从高字节到低字节)
地位地址 0x12 0x34 0x56 0x78 高位地址

六、大端小端检测方法(2015款MAC pro跑的如下代码)

#include <iostream>
/*return 1: little-endian, return 0: big-endian*/
int checkCPUendian()
{
    union
    {
        unsigned int a;
        unsigned char b;
    }c;
    c.a = 1;
    return (c.b == 1);
}
using namespace std;
int main() {
    //---------------------- (1)第一种查询方式 ----------------------//
    cout<<checkCPUendian()<<endl;//输出=> 1,表示小端(Intelx86处理器)
    //---------------------- (2)第二种查询方式 ----------------------//
    int i = 1;
    char *p = (char *)&i;
    if(*p == 1)
        printf("Little Endian");//输出=> Little Endian,表示小端(Intelx86处理器)
    else
        printf("Big Endian");
    return 0;
}

  

Reference:

https://www.ruanyifeng.com/blog/2016/11/byte-order.html

https://www.cnblogs.com/luxiaoxun/archive/2012/09/05/2671697.html

posted @ 2020-12-12 22:07  arun_yh  阅读(4827)  评论(0编辑  收藏  举报