天天看點

一起talk C栗子吧(第一百五十二回:C語言執行個體--計算機中的大小端)

各位看官們,大家好,上一回中咱們說的是socket通信位址的例子,這一回咱們說的例子是:計算機中的大小端 。閑話休提,言歸正轉。讓我們一起talk C栗子吧!

大小端據說來源于小說《格列佛遊記》,書中說:人們在争論打開雞蛋的方式是從雞蛋的大端還是小端打開雞蛋。争論不休,甚至還引起了戰争。你說說,不管你從哪一端打開雞蛋,打開的都是雞蛋呀,這有什麼可以争論的呢?還要通過戰争來解決。大家不必關注這個争論,如果真想了解其中的細節,可以看看這部小說。不過在計算機中的大小端就不像小說中争論打開雞蛋那麼簡單了,因為它有着不同的意義。

大小端表示位元組在計算機中存儲順序。它是從英文Big endian和Little endian翻譯過來的。我們使用的大部分資料存儲在多個位元組中,這些位元組的排列順序有一定排列規則:

  • 當計算機使用大端方式存儲資料時,位元組的排列順序是從高位到低位。
  • 當計算機使用小端方式存儲資料時,位元組的排列順序是從低位到高位。

這麼說,大家可能覺得很抽象,接下來我們通過具體的例子來說明什麼是大小端。例如:計算機記憶體中的某個數值:0x12345678。其中1表示高位,8表示低位。

  • 當計算機使用大端來存儲該資料時,那麼該資料在計算機中的存儲方式是:0x12345678。
  • 當計算機使用小端來存儲該資料時,那麼該資料在計算機中的存儲方式是:0x87654321。

這時有看官提問了:我們平時寫程式時也沒有體會到大小端有什麼不同呢?其實,這不怪大家,因為我們目前使用的個人計算機中絕大部分是X86架構的計算機,該架構類型的計算機都使用小端方式來存儲資料。這也就是說大家都在使用同一種存儲資料的方式,是以體會不到資料存儲的差異。在一些大型伺服器中會使用大端方式存儲資料的計算機,這類型機器,我們很少能接接觸到。大家如果不清楚自己使用的計算機屬于大小端中的哪一種,我們可以使用代碼來判斷。

#include <stdio.h>

int main()
{
    int a = ;
    int len = sizeof(int); // get the count of byte
    int i =-;
    char *p = (char*)&a;

    printf("  [address]   [value] \n");
    while(i<len)
    {
        printf("[%p]   [%x] \n",p+i,*(p+i));
        i++;
    }
    return ;
}
           

在代碼中我們把十六進制的資料指派給了一個int型變量,之是以使用十六進制的數值,是為了輸出該數值時友善觀察。大家都知道計算機中使用多個位元組存儲int型變量,使用單個位元組存儲char型變量,是以,我們把int類型變量的位址強制轉換為char類型的指針,這樣可以按照位元組的方式來檢視int型變量的存儲細節。這些細節包含:

  • int型變量的位元組數量;
  • 多個位元組的存放順序;
  • 每個位元組中存儲的資料。

下面是程式的運作結果,請大家參考:

[address]   [value] 
[]   [] 
[]   [] 
[]   [] 
[]   []
           

從上面的程式運作結果中可以看到,int型變量使用四個位元組來存儲資料,這四個位元組的位址從0x0xbfe7a880到0xbfe7a883依次排列,其中低位址0xbfe7a880存儲低位資料78,高位位址0xbfe7a883存儲高位資料12。大家結合我們上面的介紹,可以看到,該計算機使用的是小端方式存儲資料。

看官們,除了部分使用大端的計算機外,網絡通信中使用的套接字使用大端方式傳輸資料,這也是我們在介紹套接字的過程中專門插入一個章回來介紹大小端的原因。大家都知道,我們的計算機中使用小端方式存儲資料,如果使用網絡通信時需要使用大端方式來傳輸資料。這顯然是有差異的,如何處理存儲方式上的差異呢?我們在後面章回中會做詳細的介紹。

各位看官,關于計算機中大小端的例子咱們就說到這裡。欲知後面還有什麼例子,且聽下回分解 。

繼續閱讀