C語言學習篇(24)——大小端模式初探

引言:什麼是大小端模式

在計算機通信過程中,經常會遇到一個問題,是先發送數據的高字節還是先發送低字節呢?比如我們經常可以在網絡通訊協議中,都能聽到”大端(big endian)模式”這一詞,與之對應的是"小端模式(little endian)",發送方和接收方必須按照相同的字節順序來處理數據,否則就會出現錯誤。

而今天我們主要講的是計算機存儲系統的大小端,在計算機內存/硬盤中,數據是以字節為單位存儲的,於是乎有一個32位的二進制在內存中存儲時就有2種方式分佈:1.高字節對應高地址(大端模式) 2.高字節對應低地址(小端模式), 以下示意圖,感受下區別:

C語言學習篇(24)——大小端模式初探

經典筆試題:測試當前機器的大小端模式

上一篇我們詳細講解了共用體union的一些概念,如定義,使用,內存分佈等等知識點,今天我們就趁熱打鐵,使用共用體union來測試我們機器的大小端模式,先貼代碼:

<code>#include <stdio.h>

union test
{
\tint a;
\tchar b;
};

//返回值:
//\t\t 1:\t小端模式
//\t\t 0: 大端模式
int Is_Little_Endian(void)
{
\tunion test t1;
\t
\tt1.a = 1;
\t
\treturn t1.b;
}

int main(void)
{
\tint ret = Is_Little_Endian();
\t
\tif(ret == 1)
\t\tprintf("我的機器是小端模式!\\n");
\telse
\t\tprintf("我的機器是大端模式!\\n");
\t
\treturn 0;
}/<stdio.h>/<code>

代碼是不是很簡單呢~, 我們來簡單分析下:

1. 首先我們定義函數int Is_Little_Endian(void),其作用就是來測試當前機器的大小端的

  1. 我們在函數體中定義了共用體t1, 並初始化了t1.a=1; 並直接返回了t1.b
  2. 我們在主函數main中定義ret變量來接收上面函數返回的t1.b的值
  3. 根據ret的值,我們判斷機器的大小端,並打印相關信息

相信這裡大家有個疑惑,憑啥就能根據t1.b的值就能判斷機器的大小端勒? 這裡有一個很重要的概念,即共用體的本質:共用體內元素不獨立,元素之間共享同一塊內存空間,只是解析不同!!!,我們通過下圖來感受下其道理:

C語言學習篇(24)——大小端模式初探

注意共用體t1中元素b是char類型,只佔用第一個字節(內存地址為0x8的一個格子),因此我們可以根據t1.b的值來判斷機器的大小端。

編譯運行:

C語言學習篇(24)——大小端模式初探

我的測試機器就是英特爾的x86_64,就是小端模式,與運行結果一致。

到這裡如果大家還是懷疑上面代碼的測試的可靠性,我特意下載了keil c51來驗證下,同樣我們將以上的代碼原封不動貼到Keil4 C51(機器設置為AT89C51RC,相信大家對這款單片機型號不陌生吧, 滿滿的回憶~~):

C語言學習篇(24)——大小端模式初探

OK,我們軟件仿真下:

C語言學習篇(24)——大小端模式初探

簡單分析下:

1. 分別打了2個斷點(上圖紅色標記處),然後單步運行

  1. 可以看到單步到if判斷語句時,跳轉到else之後的代碼,打印了printf("我的機器是大端模式!\\n");
  2. 即說明AT89C51RC是大端模式

用指針方式測試大小端

<code>#include <stdio.h>

union test
{
\tint a;
\tchar b;
};

//返回值:
//\t\t 1:\t小端模式
//\t\t其他: \t大端模式
int Is_Little_Endian2(void)
{
\tint a = 1;
\t
\tchar b = *((char *)(&a));
\t
\treturn b;
}

int main(void)
{
\tint ret = Is_Little_Endian2();
\t
\tif(ret == 1)
\t\tprintf("我的機器是小端模式!\\n");

\telse
\t\tprintf("我的機器是大端模式!\\n");
\t
\treturn 0;
}/<stdio.h>/<code>

簡單分析:

1. 在Is_Little_Endian2函數體中, 我們定義int a,並賦值為1

  1. 我們將a取地址後,強制轉化成char *類型,即由原來執行一個int類型(4個格子)變為指向一次char類型(1個格子)的內存空間。然後解引用後賦值給b
  2. 函數返回b的值,並根據b的值判斷機器的大小端

編譯運行:

C語言學習篇(24)——大小端模式初探

結果還是一樣的,同樣用內存示意圖加深理解:

C語言學習篇(24)——大小端模式初探

小結

大端模式和小端模式本身沒有對錯,沒有優劣,理論上按照大端或小端都可以,但是要求必須存儲時和讀取時按照同樣的大小端模式來進行,否則會出錯。

現實的情況就是:有些CPU公司用大端(譬如C51單片機;有些CPU用小端(譬如ARM)(起始大部分是用小端模式),當不知道當前環境是用大端模式還是小端模式時就需要用代碼來檢測當前系統的大小端。

C語言學習篇(24)——大小端模式初探


分享到:


相關文章: