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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM