C語言中的聯合體 (記錄)

在C語言中,一種和結構體非常類似的語法,叫做共用體(Union),它的定義格式爲:

union 共用體名{
    成員列表
};

結構體和共用體的區別在於:結構體的各個成員會佔用不同的內存,互相之間沒有影響;而共用體的所有成員佔用同一段內存,修改一個成員會影響其餘所有成員。

結構體佔用的內存大於等於所有成員佔用的內存的總和(成員之間可能會存在縫隙),共用體佔用的內存等於最長的成員佔用的內存。共用體使用了內存覆蓋技術,同一時刻只能保存一個成員的值,如果對新的成員賦值,就會把原來成員的值覆蓋掉。

共用體也是一種自定義類型,可以通過它來創建變量,例如:

union data{
    int n;
    char ch;
    double f;
};
union data a, b, c;

上面是先定義共用體,再創建變量,也可以在定義共用體的同時創建變量:

union data{
    int n;
    char ch;
    double f;
} a, b, c;

如果不再定義新的變量,也可以將共用體的名字省略:

union{
     int n;
     char ch;
     double f;
} a, b, c;

共用體 data 中,成員 f 佔用的內存最多,爲 8 個字節,所以 data 類型的變量(也就是 a、b、c)也佔用 8 個字節的內存,請看下面的演示:

#include <stdio.h>

union data{
    int n;
    char ch;
    short m;
};

int main(){
    union data a;
    printf("%d, %d\n", sizeof(a), sizeof(union data) );
    a.n = 0x40;
    printf("%X, %c, %hX\n", a.n, a.ch, a.m);
    a.ch = '9';
    printf("%X, %c, %hX\n", a.n, a.ch, a.m);
    a.m = 0x2059;
    printf("%X, %c, %hX\n", a.n, a.ch, a.m);
    a.n = 0x3E25AD54;
    printf("%X, %c, %hX\n", a.n, a.ch, a.m);

return 0;
}

運行結果:

4, 4
40, @, 40
39, 9, 39
2059, Y, 2059
3E25AD54, T, AD54

這段代碼不但驗證了共用體的長度,還說明共用體成員之間會相互影響,修改一個成員的值會影響其他成員。

要想理解上面的輸出結果,弄清成員之間究竟是如何相互影響的,就得了解各個成員在內存中的分佈。以上面的 data 爲例,各個成員在內存中的分佈如下:

成員 n、ch、m 在內存中“對齊”到一頭,對 ch 賦值修改的是前一個字節,對 m 賦值修改的是前兩個字節,對 n 賦值修改的是全部字節。也就是說,ch、m 會影響到 n 的一部分數據,而 n 會影響到 ch、m 的全部數據。

接下來是判斷大小端的方法:

大端模式,是指數據的高字節保存在內存的低地址中,而數據的低字節保存在內存的高地址中,這樣的存儲模式有點兒類似於把數據當作字符串順序處理:地址由小向大增加,而數據從高位往低位放;這和我們的閱讀習慣一致。

小端模式,是指數據的高字節保存在內存的高地址中,而數據的低字節保存在內存的低地址中,這種存儲模式將地址的高低和數據位權有效地結合起來,高地址部分權值高,低地址部分權值低。

測試代碼:

#include <stdlib.h>
#include <stdio.h>

union data{
        int c;
        char a;
        short b;
};

int test(){
        unsigned int num = 0x12345678;
        unsigned short test = num;
        if(test == 0x1234)
                return 1;//big
        else
                return 0;//little
}

int main(){
        int i = test();
        if(i == 0)
                printf("little\n");
        else
                printf("big\n");
        printf("test2\n");
        union data a;
        a.c = 0x12345678;
        printf("%x %x %x\n",a.a,a.b,a.c);
        char *p1=&a.a,*p2=&a.b,*p3=&a.c,*p4=&a;
        printf("a:%ld b:%ld c:%ld union:%ld\n",p1,p2,p3,p4);
        if(a.a == 0x78)
                printf("little\n");
        else
                printf("big\n");
}

參考:C語言中文網

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