union介紹
共用體,也叫聯合體,在一個“聯合”內可以定義多種不同的數據類型, 一個被說明為該“聯合”類型的變量中,允許裝入該“聯合”所定義的任何一種數據,這些數據共享同一段內存,以達到節省空間的目的。union變量所占用的內存長度等於最長的成員的內存長度。
union與struct比較
先看一個關於struct的例子:
struct student { char mark; long num; float score; };
其struct的內存結構如下,sizeof(struct student)的值為12bytes。
下面是關於union的例子:
union test { char mark; long num; float score; };
sizeof(union test)的值為4。因為共用體將一個char類型的mark、一個long類型的num變量和一個float類型的score變量存放在同一個地址開始的內存單元中,而char類型和long類型所占的內存字節數是不一樣的,但是在union中都是從同一個地址存放的,也就是使用的覆蓋技術,這三個變量互相覆蓋,而這種使幾個不同的變量共占同一段內存的結構,稱為“共用體”類型的結構。其union類型的結構如下:
因union中的所有成員起始地址都是一樣的,所以&a.mark、&a.num和&a.score的值都是一樣的。
不能如下使用:
union test a; printf("%d", a); //錯誤
由於a的存儲區有好幾種類型,分別占不同長度的存儲區,僅寫共用體變量名a,這樣使編譯器無法確定究竟輸出的哪一個成員的值。
printf("%d", a.mark); //正確
測試大小端
union的一個用法就是可以用來測試CPU是大端模式還是小端模式:
#include <iostream> using namespace std; void checkCPU() { union MyUnion{ int a; char c; }test; test.a = 1; if (test.c == 1) cout << "little endian" <<endl; else cout << "big endian" <<endl; } int main() { checkCPU(); return 0; }
舉例,代碼如下:
#include <iostream> using namespace std; union test { char mark; long num; float score; }a; int main() { // cout<<a<<endl; // wrong a.mark = 'b'; cout<<a.mark<<endl; // 輸出'b' cout<<a.num<<endl; // 98 字符'b'的ACSII值 cout<<a.score<<endl; // 輸出錯誤值 a.num = 10; cout<<a.mark<<endl; // 輸出換行 非常感謝suxin同學的指正 cout<<a.num<<endl; // 輸出10 cout<<a.score<<endl; // 輸出錯誤值 a.score = 10.0; cout<<a.mark<<endl; // 輸出空 cout<<a.num<<endl; // 輸出錯誤值 cout<<a.score<<endl; // 輸出10 return 0; }
C++中union
上面總結的union使用法則,在C++中依然適用。如果加入對象呢?
#include <iostream> using namespace std; class CA { int m_a; }; union Test { CA a; double d; }; int main() { return 0; }
上面代碼運行沒有問題。
如果在類CA中添加了構造函數,或者添加析構函數,就會發現程序會出現錯誤。由於union里面的東西共享內存,所以不能定義靜態、引用類型的變量。由於在union里也不允許存放帶有構造函數、析構函數和復制構造函數等的類的對象,但是可以存放對應的類對象指針。編譯器無法保證類的構造函數和析構函數得到正確的調用,由此,就可能出現內存泄漏。所以,在C++中使用union時,盡量保持C語言中使用union的風格,盡量不要讓union帶有對象。
參考:http://www.jellythink.com/archives/468