C 語言快速導覽 - 聯合

聯合為早期 C 語言為了解決記憶體不足而有的資料型態,其定義與宣告與結構類似,不同之處為聯合的所有成員佔用相同的記憶體空間,因此儲存到聯合的值會以該成員具有儲存範圍最大的資料型態為優先,也就是佔用到最多位元組數的資料型態。



聯合的定義格式如下圖



下例中替聯合 data 定義了兩個成員,分別是 int 及 double 型態
#include <stdio.h>

union data {
    int vi;
    double vd;
};

int main(void)
{
    union data a;
    
    a.vi = 11;
    printf("a = (%d, %f)\n", a.vi, a.vd);
    
    a.vd = 22.0;
    printf("a = (%d, %f)\n", a.vi, a.vd);
    
    return 0;
}

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:uniondata.c
    功能:示範聯合的使用
    作者:張凱慶
    時間:西元2010年4月 */


編譯後執行,結果如下



我們可以看出在 double 型態的成員被給值後, int 型態的成員自動被歸 0 。因此聯合的實際運用僅限於某一個成員,但實際仍須視編譯器、系統如何實作。


下例中利用 sizeof 運算子比較結構與聯合實際佔用記憶體空間的差異
#include <stdio.h>

union udata {
    int x;
    long y;
    double z;
    char *a;
};

struct sdata {
    int x;
    long y;
    double z;
    char *a;
};

int main(void)
{
    printf("%d\n", sizeof(union udata));
    printf("%d\n", sizeof(struct sdata));
    
    return 0;
}

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:unionstruct.c
    功能:比較聯合與結構的大小
    作者:張凱慶
    時間:西元2010年4月 */


編譯後執行,如下



由於 double 型態佔 8 個 byte 的位元組數,所以聯合變數 udata 就佔用 8 個 byte 的位元組數。結構變數 sdata 佔 20 個 byte 的位元組數,這是因為所有的成員 4 + 4 + 8 + 1 需 17 個位元組數,結構另有邊界對齊的狀況,所以此例中另外又加上 3 個位元組數。




5 則留言:

匿名 提到...

很好的教學,謝謝!

匿名 提到...

很好的教學,謝謝!

sjgau 提到...

union,
我把他,解釋為 共同使用同一塊記憶體。
目的何在?
有可能是為了節省記憶體。
我是拿來偷偷的看一下 float, double 的每一個
bit 的使用情況。

union u_name {
int i4;
unsigned char uc[4];
float dbl;
} u2;

我讓 u2.dbl= 1.23e45;
我可以把 uc[0] 到 uc[3]的 每一個 byte
轉換成 二進位的 bits, 然後 列印出來 觀察。

大家 以為如何?

Ken 提到...

sdata 佔 20 個 byte 應該不是因為 structure Alignment,而是 char *a 占用四個 byte ==> C語言的指標長度為 4byte。

Kiss 提到...

我用相同程式 sdata印出來結果是24耶
後來去查一下邊界的問題,得到以下看法
int(4) + long(4) + char*(4) + double(8)
= 20
但又因為此結構最寬的型態是double(8)
所以此結構長度必須為8的倍數
所以20以上的最小8的倍數為 8*3=24
不曉得我這樣看法對不對