什麼是大端和小端?
為什麼要顛倒位元組儲存順序?
該部落格上撰寫的文章是出於教學目的而創建的。 另外,文章中的資訊可能不正確,請謹慎。
在編碼時,您可能已透過網路傳送資料或讀取特定檔案。 在某些情況下,得出的值與我的預期完全不同。 這種現象的正式名稱是Endianness排列法。 也就是說,它們被稱為 Big Endian 和 Little Endian。
CPU在記憶體中儲存4位元組int型資料時,並不是將其作為一個整體打包,而是將其分成1位元組的區塊,並依序儲存在位址中。 這時候就看你是從最大位元(MSB)開始依序排列,還是從最小位元(LSB)開始倒序排列。 資料在記憶體中的放置方式完全不同。
如果你按照直觀的順序放置數字,就像一個人讀取它們一樣,那麼它們就是大端字節序,如果你以相反的順序放置它們以便機器更容易計算它們,那麼它們就是小端字節序。 大多數現代PC,例如我們主要使用的Intel或AMD CPU,都採用小端系統。
我們自己用程式碼來驗證一下。
#include <iostream>
#include <iomanip>
int main() {
//4位元組十六進制整數數據
unsigned int number = 0x12345678;
//轉換指標以檢查每個位元組在記憶體中的儲存方式
unsigned char* bytePtr = reinterpret_cast<unsigned char*>(&number);
for (int i = 0; i < sizeof(int); ++i) {
std::cout << "&bytePtr[" << i << "] : 0x"
<< std::hex << std::setw(2) << std::setfill('0')
<< (int)bytePtr[i] << std::endl;
}
/*
* 基於小端系統
* &bytePtr[0] : 0x78 //最小單元 (LSB) 先進入最低位址
* &bytePtr[1] : 0x56
* &bytePtr[2] : 0x34
* &bytePtr[3] : 0x12
*
* 基於大端系統
* &bytePtr[0] : 0x12 //最大單元(MSB)首先進入最低位址。
* &bytePtr[1] : 0x34
* &bytePtr[2] : 0x56
* &bytePtr[3] : 0x78
*/
return 0;
}
這裡出現一個問題。無論如何都會儲存相同的值, 為什麼他們採用一種不直觀的倒置資料儲存方法,例如小尾數法? 這是由於CPU內部加法器的設計和類型轉換的效率。
當CPU對兩個數進行加減運算時,必須從1的位置開始計算,也就是最小的位數,才能進行進位。 在小端位元組序中,最小單元(LSB)位於記憶體中的第一個位址, CPU一讀取內存,就可以立即開始執行算術運算。 此外,當透過將 4 位元組整數截斷為 1 位元組(字元)進行向下轉換時, 硬體邏輯大大簡化,因為只需要提取記憶體的起始位址,無需額外的位址計算。
另一方面,大端字節序對於人類在查看記憶體轉儲時讀取起來很直觀, 當比較兩個數字的大小時,它的優點是從第一個數字開始比較。 因此,為了避免交換資料時出現混亂, 在互聯網協定 (TCP/IP) 等網路標準通訊中,使用大端位元組序作為標準。