大端和小端是指數據在內存中的存儲模式,它由 CPU 決定:
1) 大端模式(Big-endian)是指將數據的低位(比如 1234 中的 34 就是低位)放在內存的高地址上,而數據的高位(比如 1234 中的 12 就是高位)放在內存的低地址上。這種存儲模式有點兒類似於把數據當作字符串順序處理,地址由小到大增加,而數據從高位往低位存放。
2) 小端模式(Little-endian)是指將數據的低位放在內存的低地址上,而數據的高位放在內存的高地址上。這種存儲模式將地址的高低和數據的大小結合起來,高地址存放數值較大的部分,低地址存放數值較小的部分,這和我們的思維習慣是一致,比較容易理解。
爲什麼有大小端模式之分?
計算機中的數據是以字節(Byte)爲單位存儲的,每個字節都有不同的地址。現代 CPU 的位數(可以理解爲一次能處理的數據的位數)都超過了 8 位(一個字節),PC機、服務器的 CPU 基本都是 64 位的,嵌入式系統或單片機系統仍然在使用 32 位和 16 位的 CPU。
對於一次能處理多個字節的CPU,必然存在着如何安排多個字節的問題,也就是大端和小端模式。以 int 類型的 0x12345678 爲例,它佔用 4 個字節,如果是小端模式(Little-endian),那麼在內存中的分佈情況爲(假設從地址 0x 4000 開始存放):
內存地址 0x4000 0x4001 0x4002 0x4003
存放內容 0x78 0x56 0x34 0x12
如果是大端模式(Big-endian),那麼分佈情況正好相反:
內存地址 0x4000 0x4001 0x4002 0x4003
存放內容 0x12 0x34 0x56 0x78
我們的 PC 機上使用的是 X86 結構的 CPU,它是小端模式;51 單片機是大端模式;很多 ARM、DSP 也是小端模式(部分 ARM 處理器還可以由硬件來選擇是大端模式還是小端模式)。
藉助共用體,我們可以檢測 CPU 是大端模式還是小端模式,請看代碼:
#include <stdio.h>
int main()
{
union{
int n;
char ch;
} data;
if(data.ch == 1){
printf("Little-endian\n");
}else{
printf("Big-endian\n");
}
return 0;
}
在PC機上的運行結果:
Little-endian
共用體的各個成員是共用一段內存的。1 是數據的低位,如果 1 被存儲在 data 的低字節,就是小端模式,這個時候 data.ch 的值也是 1。如果 1 被存儲在 data 的高字節,就是大端模式,這個時候 data.ch 的值就是 0。