最近工作中有用到一個知識點,就是大小端,當然這是一個小的知識點,為什麼寫一個博文呢,我其實是想測試一下chatGPT,所以我開始將自己的想法告訴這個chatbot,讓他給我一些寫博文的建議,並且給我解答了一些疑惑,今天將自己的學習筆記整理出來展示給大家(by the way,一個有用的搜尋引擎和chatbot對我們的工作有著事半功倍的作用,並且它的思路很明顯比我更好,如果只是單純的用在學習上,我覺得這個簡直是百科全書)。
廢話不多說了,正文開始。
在計算機中,位元組序指的是在記憶體中,多位元組資料的位元組存放順序。大小端是電腦架構中的一個概念,用於表示在多位元組資料型別中,位元組的順序。在不同的電腦架構中,位元組順序可能不同。一些處理器將最高位位元組儲存在地址最低的位置,這被稱為「大端位元組序」(高位位元組排放在記憶體的低地址端,低位位元組排放在記憶體的高地址端),而另一些處理器將最低位位元組儲存在地址最低的位置,這被稱為「小端位元組序」(低位位元組排放在記憶體的低地址端,高位位元組排放在記憶體的高地址端)。
例如,假設我們要儲存十六進位制數0x12345678(十進位制數為305419896),在大端位元組序下,它的儲存順序為:
12 34 56 78
而在小端位元組下,則為:
78 56 34 12
以上從左到右=》 低地址(高位)到高地址(低位)。偷個圖:
大端和小端的概念最初由IBM的工程師Danny Cohen提出。這兩種位元組序最初是由不同的計算機廠商開發出來的。早期的計算機在內部記憶體和CPU之間使用通訊線,用於傳送和接收資料。這些通訊線被設計為雙向的,可以在讀和寫時使用。因此,資料的位元組順序是很重要的。在當時的計算機中,大端位元組序被廣泛採用。
這是由電腦架構的設計決定的。在早期的計算機設計中,記憶體是以字(word)為單位進行讀寫的,字的長度不同,如16位元、32位元或64位元等。在讀寫資料時,需要確定資料的位元組順序,以便正確地處理資料。在計算機系統中,以位元組為單位,所以每個地址單元都對應一個位元組,一個位元組為8bit。但是在C語言中除了8bit的char外,還有16bit的short,32bit的long。另外對於位數大於8位元的處理器,例如16位元或者32位元的處理器,由於暫存器大於一個位元組,那麼必然存在一個如何將多個位元組安排的問題。因此就導致了大端儲存和小端儲存模式。
在大端位元組序中,最高有效位在最低的地址上,符合人類的習慣,容易理解和記憶。而在小端位元組序中,最低有效位在最低的地址上,這種方式更容易實現,因為它可以讓計算機在處理位元組序列時不需要額外的轉換操作,只需要按照順序依次讀寫即可。
實際上,不同的處理器架構和作業系統都有不同的位元組序規則,例如x86架構的處理器使用小端位元組序,而PowerPC架構的處理器使用大端位元組序。因此,在進行資料傳輸或資料交換時,需要考慮資料的位元組序,以確保資料的正確傳輸和解析。
大小端(Endian)是指計算機中位元組的排列順序。它分為大端(Big-endian)和小端(Little-endian)。大端表示高位位元組儲存在低地址,而小端表示低位位元組儲存在低地址。大小端的發展歷史可以追溯到計算機的早期發展階段。
1960s:大小端的概念最早可以追溯到20世紀60年代,IBM的System/360系列計算機採用了大端位元組序。這種位元組序的設計與人類閱讀數位的方式相似,即從高位到低位。
1970s:在20世紀70年代,DEC公司推出了PDP-11系列計算機,採用了小端位元組序。小端位元組序的優勢在於,對於多位元組整數的部分存取和計算更加方便,因為低位位元組總是儲存在最低的地址。
1980s:隨著計算機技術的發展,許多不同的處理器架構開始出現。例如,Motorola 68000系列處理器採用大端位元組序,而Intel x86系列處理器採用小端位元組序。這導致了計算機領域內的大小端之爭。
1990s:在20世紀90年代,隨著網路技術的普及,計算機之間的資料交換變得越來越重要。因此,網路位元組序(Network Byte Order)的概念應運而生。網路位元組序採用大端位元組序,以確保不同處理器架構之間的資料交換能夠順利進行。
2000s至今:在21世紀,計算機技術繼續發展,處理器架構也趨於多樣化。許多處理器,如ARM和PowerPC,支援大小端可設定,使得系統設計者可以根據實際需求選擇合適的位元組序。此外,一些程式語言和庫也提供了跨平臺的位元組序轉換功能,以便在不同位元組序的系統之間進行資料交換。
在早期的電腦架構中,大端位元組序是主流的儲存方式。但是,後來隨著英特爾處理器的流行,小端位元組序逐漸成為主流。英特爾處理器採用小端位元組序的主要原因是,其實現簡單且效率高。同時,小端位元組序的處理方式也更符合人的直觀感覺,因為我們通常是從低位到高位依次讀取資料。總之,大小端的發展歷史反映了計算機技術的演進和處理器架構的多樣化。如今,大小端問題已經不再是一個嚴重的障礙,因為現代處理器和軟體都提供了靈活的解決方案來應對位元組序差異。
在計算機中,大端(Big-Endian)和小端(Little-Endian)是兩種不同的資料儲存方式。下面我們詳細學習一下大小端的實現原理和儲存方式,具體定義如下:
大端位元組序(Big-Endian):在大端位元組序中,資料的高位位元組儲存在低位地址上,而資料的低位位元組儲存在高位地址上。這種方式類似於我們人類習慣的順序,從左到右,高位到低位。
儲存方式:假設我們有一個32位元整數0x12345678,其記憶體地址為0x1000。在大端位元組序的系統中,該整數的儲存方式如下:
地址 資料 0x1000 -> 0x12 (高位位元組) 0x1001 -> 0x34 0x1002 -> 0x56 0x1003 -> 0x78 (低位位元組)
小端位元組序(Little-Endian):在小端位元組序中,資料的低位位元組儲存在低位地址上,而資料的高位位元組儲存在高位地址上。這種方式與大端位元組序相反,但是在實際應用中也有很多優點,例如可以方便地進行低位對齊。
儲存方式:同樣以32位元整數0x12345678為例,其記憶體地址為0x1000。在小端位元組序的系統中,該整數的儲存方式如下:
地址 資料 0x1000 -> 0x78 (低位位元組) 0x1001 -> 0x56 0x1002 -> 0x34 0x1003 -> 0x12 (高位位元組)
大小端的實現原理和儲存方式主要體現在多位元組資料在記憶體中的排列順序。大端位元組序將高位位元組儲存在低地址,而小端位元組序將低位位元組儲存在低地址。不同的處理器架構可能採用不同的位元組序,因此在進行跨平臺資料交換時需要注意位元組序的轉換。兩種位元組序的區別在於位元組的儲存順序,而不是位的儲存順序。在多位元組資料型別(例如整數、浮點數等)儲存時,其位元組序決定了位元組在記憶體中的排列順序。
下面是一個示意圖,展示了一個32位元整型數在大端和小端位元組序下的儲存方式:
大端位元組序: 0x12345678 +--------+ | 12 | 34| +--------+ | 56 | 78| +--------+ 小端位元組序: 0x12345678 +--------+ | 78 | 56| +--------+ | 34 | 12| +--------+
不同的處理器架構可能採用不同的位元組序規則。以下是一些常見處理器架構及其位元組序規則:
Intel x86/x64(IA-32/IA-64): 位元組序規則:小端(Little-endian) 說明:Intel x86和x64架構處理器廣泛應用於個人計算機和伺服器領域。這些處理器採用小端位元組序,將低位位元組儲存在低地址。
ARM: 位元組序規則:大小端可設定(Configurable Endianness) 說明:ARM處理器廣泛應用於嵌入式系統和移動裝置。ARM架構支援大小端可設定,系統設計者可以根據實際需求選擇合適的位元組序。大多數情況下,ARM處理器預設採用小端位元組序。
MIPS: 位元組序規則:大小端可設定(Configurable Endianness) 說明:MIPS處理器應用於嵌入式系統、網路裝置和遊戲機等領域。MIPS架構支援大小端可設定,允許系統設計者根據需求選擇位元組序。通常情況下,MIPS處理器預設採用大端位元組序。
PowerPC: 位元組序規則:大小端可設定(Configurable Endianness) 說明:PowerPC處理器應用於嵌入式系統、伺服器和遊戲機等領域。PowerPC架構支援大小端可設定,允許系統設計者根據需求選擇位元組序。通常情況下,PowerPC處理器預設採用大端位元組序。
Motorola 68000: 位元組序規則:大端(Big-endian) 說明:Motorola 68000系列處理器曾廣泛應用於個人計算機、遊戲機和嵌入式系統等領域。這些處理器採用大端位元組序,將高位位元組儲存在低地址。
SPARC: 位元組序規則:大端(Big-endian) 說明:SPARC處理器主要應用於高效能運算和伺服器領域。SPARC架構採用大端位元組序,將高位位元組儲存在低地址。
需要注意的是,不同處理器架構的位元組序規則可能會影響跨平臺資料交換。在進行資料交換時,需要注意位元組序的轉換,以確保資料的正確性。許多程式語言和庫提供了跨平臺的位元組序轉換功能,以便在不同位元組序的系統之間進行資料交換。
簡單將上面內容整理一下(方便直接看結論的童靴):
大小端 | CPU |
Big Endian | PowerPC, MIPS, Mac OS, IBM , Sun, Mototola 68000, SPARC |
Little Endian | x86, x64, DEC, Windows |
遇到大小端的問題,我們如何解決呢,首先就是判斷機器的位元組序(是大端位元組序還是小端位元組序),然後進行轉換。
給一個C++判斷機器位元組序的程式碼:
// Judge the endian of the local system inline bool isLittleEndian() { union { uint32_t i; char c[4]; } test = {0x01020304}; return test.c[0] == 0x04; }
或者下面例子:
#include <iostream> // 判斷機器位元組序的函數 bool isLittleEndian() { int num = 1; char *ptr = reinterpret_cast<char*>(&num); return *ptr == 1; } int main() { if (isLittleEndian()) { std::cout << "This machine is Little-endian." << std::endl; } else { std::cout << "This machine is Big-endian." << std::endl; } return 0; }
下面是一個轉換大小端位元組序的例子,比如你的機器需要大端,所以處理不同作業系統的時候,你需要考慮先判斷系統位元組序的,然後不同的需要轉換,畢竟我們上面也提到了不同系統位元組序不同。
#include <iostream> // 轉換16位元整數的位元組序 uint16_t swapEndian16(uint16_t value) { return (value << 8) | (value >> 8); } // 轉換32位元整數的位元組序 uint32_t swapEndian32(uint32_t value) { return ((value << 24) & 0xFF000000) | ((value << 8) & 0x00FF0000) | ((value >> 8) & 0x0000FF00) | ((value >> 24) & 0x000000FF); } // 轉換64位元整數的位元組序 uint64_t swapEndian64(uint64_t value) { return ((value << 56) & 0xFF00000000000000) | ((value << 40) & 0x00FF000000000000) | ((value << 24) & 0x0000FF0000000000) | ((value << 8) & 0x000000FF00000000) | ((value >> 8) & 0x00000000FF000000) | ((value >> 24) & 0x0000000000FF0000) | ((value >> 40) & 0x000000000000FF00) | ((value >> 56) & 0x00000000000000FF); } int main() { uint16_t num16 = 0x1234; uint32_t num32 = 0x12345678; uint64_t num64 = 0x123456789ABCDEF0; std::cout << "Original 16-bit value: " << std::hex << num16 << std::endl; std::cout << "Swapped 16-bit value: " << std::hex << swapEndian16(num16) << std::endl; std::cout << "Original 32-bit value: " << std::hex << num32 << std::endl; std::cout << "Swapped 32-bit value: " << std::hex << swapEndian32(num32) << std::endl; std::cout << "Original 64-bit value: " << std::hex << num64 << std::endl; std::cout << "Swapped 64-bit value: " << std::hex << swapEndian64(num64) << std::endl; return 0; }
上面的範例展示瞭如何在C++中判斷機器的位元組序以及如何轉換大小端位元組序。在實際應用中,可能大家需要根據自己的需求對程式碼進行調整和優化,我自己也是。(當然如果使用python,可能更方便)