計算機的大小端


計算機的大小端指的是不同的字節順序儲存方式。

0x1A2B3C4D,總共四個字節,兩個十六進制數表示一個字節,高位字節為0x1A,低位字節為0x4D;中間兩個字節分別為0x2B和0x3C;數值0x1A2B3C4D想要在計算機中正確使用,就必須要考慮在內存中將其對應的四個字節合理存儲。

對於一個數值多個字節順序存儲就有兩種存儲方式:

  • 大端:(Big-Endian):就是把數值的高位字節放在內存的低位地址上,把數值的低位字節放在內存的高位地址上(低字節在后,高字節在前)
    • 人類習慣讀寫大端字節序,比如1234 -> 一千兩百三十四。
    • 除了計算機的內部處理,其他的場合幾乎都是大端字節序,比如網絡傳輸和文件儲存
    • 優點:符號位的判定固定為第一個字節,容易判斷正負。高位字節也容易進行大小對比
舉例:
內存低地址 --------------------> 內存高地址
0x1A | 0x2B | 0x3C | 0x4D
高位字節 <-------------------- 低位字節
  • 小端:Little-Endian):就是把數值的高位字節放在高位的地址上,低位字節放在低位地址上(低字節在前,高字節在后)
    • 為什么會有小端字節序?計算機電路先處理低位字節,效率比較高,因為計算都是從低位開始的。所以,計算機的內部處理都是小端字節序。
    • 123 + 342 -> 先從個位開始算,再十位,百位
    • 優點:強制轉換數據不需要調整字節內容,1、2、4字節的存儲方式一樣。
舉例:
內存低地址 --------------------> 內存高地址
0x4D | 0x3C | 0x2B | 0x1A
低位字節 --------------------> 高位字節

注意:

  1. 不管是大端法還是小端法存儲,計算機在內存中存放數據的順序都是從地址到高地址所不同的是首先取低字節的數據存放在低地址還是取高字節數據存放在低地址。
  2. 大小端是數據在存儲時的表現,而不是在寄存器中參與運算時的表現
  3. 計算機處理字節序的時候,不知道什么是高位字節,什么是低位字節,也並不存在所謂的數據類型,比如char,int等。它只知道按順序讀取字節,先讀第一個字節,再讀第二個字節,如果是大端字節序,先讀到的就是高位字節,后讀到的就是低位字節。小端字節序正好相反
  4. 所謂的數據類型,比如char,int等,在代碼中的作用就是讓編譯器知道每次應該從那個地址起始讀取多少位的數據,賦值給相應的變量

舉例,16位整數:

buf是整個數據塊在內存中的起始地址,offset是當前正在讀取的位置

大端:第一個字節((高位字節)左移8位(即后面添8個0),然后再與第二個字節進行或運算。

x = buf[offset] << 8 | buf[offset+1];

小端:第二個字節左移8位,然后再與第一個字節(低位字節)進行或運算。

x = buf[offset+1] << 8 | buf[offset];

如何用代碼檢測用的是大端還是小端

  • 借助聯合體union的特性實現(union類型數據所占的內存空間等於其最大的成員所占的空間,
int main(){
    union{
      int a;  //4 bytes      
      char b; //1 byte    
    } data;

    data.a = 1; //占4 bytes,十六進制可表示為 0x 00 00 00 01高字節->低字節
                     //b因為是char型只占1Byte,a因為是int型占4Byte   
                     //所以,在聯合體data所占內存中,b所占內存等於a所占內存的低地址部分     
    if(1 == data.b){ //走該case說明a的低字節,被取給到了b,即a的低字節存在了聯合體所占內存的(起始)低地址,符合小端模式特征      
        printf("Little_Endian\n");
     } else { 0 == data.b
        printf("Big_Endian\n");
     }
   return 0;
}
  • 通過將int強制類型轉換成char單字節,判斷起始存儲位置內容實現
int main(){
    int a = 1; //占4 bytes,十六進制可表示為 0x 00 00 00 01    
                   //b相當於取了a的低地址部分     
     char *b =(char *)&a; //占1 byte    
      if (1 == *b) {//走該case說明a的低字節,被取給到了b,即a的低字節對應a所占內存的低地址,符合小端模式特征        
          printf("Little_Endian!\n");
    } else {
          printf("Big_Endian!\n");
    }
    return 0;
}

 

Reference:

  1. https://www.jianshu.com/p/633b52b7baec
  2. https://www.ruanyifeng.com/blog/2016/11/byte-order.html


免責聲明!

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



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