大端小端及其union的練習題

看了這個例子,一定會有這樣的疑問:應該是00 00 00 01,爲什麼會是這樣的

    vs2013是小端存儲,下面的這個圖從左到右地址是由低到高。

比如0x11223344在大端機上是11223344,在小端機上是44332211。

大端:低地址存高位

小端:低地址存低位 (小弟弟)

先來說清楚,32位內存地址的,雖然我們在看一個二進制數的時候比如01111011,是從後往前看的,這樣看來從左到右是高地址到低地址,而在內存中,一般是由低地址到高地址的,可以看下面的這個圖:

左邊的0x0000000E從上到下是從小到大的,所以看存儲的一個數在大端機上的是怎麼樣的,在小端機上是怎麼樣的。反正從左到右是低地址到高地址。

上面說的高位低位指的是權重,比如說1234這個數字,1的權重是千,1就是高位,高低位是相對的。

位指的是權重

如何判斷數據的高位與低位因爲位指的是權重,那麼比如說1234這個數字,1的權重是千,1就是高位,高低位是相對的。

比如對於11223344來說,他的最低位就是4,最高位就是1,則在大端機器上是11223344,在小端機器上是44332211

爲什麼有大端小端之分,因爲在計算機系統中,我們是以字節爲單位的,每個地址單元都對應着一個字節,一個字節爲8bit。
但是在C語言中除了8bit的char之外,還有16bit的short型,32bit的long型(要看具體的編譯器),另外,對於位數大於8位的處理器。例如16位或者32位的處理器,
由於寄存器寬度大於一個字節,那麼必然存在着一個如果將多個字節安排的問題(也就是將數據的字節如何與內存中的地址對應的問題)。因此就導致了大端存儲模式和小端存儲模式。
看一個例題:在小端模式下,下面的代碼輸出是

#include<iostream>
using namespace std;

union Un
{
    short a;//2
    char b;//實際對齊數是1
}un;//總體對齊數是2

int main()
{
    char p[] = {2,1};
    Un*n = (Un*)p;//這個是將p指針擴充爲Un大小的(爲兩個子節),所以是
    printf("%d,%d\n",n->a,n->b);

    return 0;

}

 

#include<iostream>
using namespace std;

union Un
{
    short a;//對齊數是2
    char b;// 對齊數是1
}un;//總體對齊數是2

int main()
{

    char p[] = {2,1};//00000010,0000 0001
    Un*n = (Un*)p;//擴充爲兩個字節的,,這樣識別的16位就是一個數,這個其實是將char 數組裏的賦值給聯合體裏的變量。
    //00000010 00000001
    //如果是小端機器,說明將
    printf("%d,%d\n",n->a,n->b);//聯合體,所以a和b共用一塊內存,所以是,所以用n指針去訪問肯定是0000 0001 0000 0010。因爲輸出是%d,也就是4個子節,所以不用截斷,
    //也就是258 而後面的b是一個字節,所以是需要截斷的,所以是0000 0001 0000 0010的後八位,所以是2
//這個的之所以沒有覆蓋是因爲,他實際訪問的是p指向的那塊內存,而不是通過賦值,所以是不會覆蓋的

    // 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010  


    /*
    un.a = 1, un.b = 2; //0000 0001 0000 0010。
    printf("%d,%d\n", un.a, un.b);//輸出爲%d,是int類型的。所以肯定是2,然後將其擴充爲4個子節
    */
    return 0;

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章