C 中union的使用

2021-06-21 10:27:45 字數 3414 閱讀 6321

聯合(union)在c/c++裡面見得並不多,但是在一些對記憶體要求特別嚴格的地方,聯合又是頻繁出現,那麼究竟什麼是聯合、怎麼去用、有什麼需要注意的地方呢?就這些問題,我試著做一些簡單的回答,裡面肯定還有不當的地方,歡迎指出!

1、什麼是聯合?

「聯合」是一種特殊的類,也是一種構造型別的資料結構。在乙個「聯合」內可以定義多種不同的資料型別, 乙個被說明為該「聯合」型別的變數中,允許裝入該「聯合」所定義的任何一種資料,這些資料共享同一段記憶體,已達到節省空間的目的(還有乙個節省空間的型別:位域)。 這是乙個非常特殊的地方,也是聯合的特徵。另外,同struct一樣,聯合預設訪問許可權也是公有的,並且,也具有成員函式。

2、聯合與結構的區別?

「聯合」與「結構」有一些相似之處。但兩者有本質上的不同。在結構中各成員有各自的記憶體空間, 乙個結構變數的總長度是各成員長度之和(空結構除外,同時不考慮邊界調整)。而在「聯合」中,各成員共享一段記憶體空間, 乙個聯合變數的長度等於各成員中最長的長度。應該說明的是, 這裡所謂的共享不是指把多個成員同時裝入乙個聯合變數內, 而是指該聯合變數可被賦予任一成員值,但每次只能賦一種值, 賦入新值則衝去舊值。

下面舉乙個例了來加對深聯合的理解。

例4: 

#include

void main()

half;

}num;

num.i=0x4241; /*聯合成員賦值*/

printf("%c%c\n", num.half.first, num.half.second);

num.half.first='a'; /*聯合中結構成員賦值*/

num.half.second='b';

printf("%x\n", num.i);

getchar();

}輸出結果為: 

ab 6261

從上例結果可以看出: 當給i賦值後, 其低八位也就是first和second的值; 當給first和second賦字元後, 這兩個字元的ascii碼也將作為i 的低八位和高八位。

3、如何定義?

例如:union test

int office;

char teacher[5];

};定義了乙個名為test的聯合型別,它含有兩個成員,乙個為整型,成員名office;另乙個為字元陣列,陣列名為teacher。聯合定義之後,即可進行聯合變數說明,被說明為test型別的變數,可以存放整型量office或存放字元陣列teacher。

4、如何說明?

聯合變數的說明有三種形式:先定義再說明、定義同時說明和直接說明。

以test型別為例,說明如下:

1) union test

; union test a,b; /*說明a,b為test型別*/

2) union test

a,b;

3) union 

a,b;

經說明後的a,b變數均為test型別。a,b變數的長度應等於test的成員中最長的長度,即等於teacher陣列的長度,共5個位元組。a,b變數如賦予整型值時,只使用了4個位元組,而賦予字元陣列時,可用5個位元組。

5、如何使用?

對聯合變數的賦值,使用都只能是對變數的成員進行。聯合變數的成員表示為: 

聯合變數名.成員名 

例如,a被說明為test型別的變數之後,可使用a.class、a.office 

不允許只用聯合變數名作賦值或其它操作,也不允許對聯合變數作初始化賦值,賦值只能在程式中進行。

還要再強調說明的是,乙個聯合變數,每次只能賦予乙個成員值。換句話說,乙個聯合變數的值就是聯合變員的某乙個成員值。

6、匿名聯合

匿名聯合僅僅通知編譯器它的成員變數共同享乙個位址,而變數本身是直接引用的,不使用通常的點號運算子語法.

例如:#include

void main()

; test=5;

c='a';

std::cout《正如所見到的,聯合成分象宣告的普通區域性變數那樣被引用,事實上對於程式而言,這也正是使用這些變數的方式.另外,儘管被定義在乙個聯合宣告中,他們與同乙個程式快那的任何其他區域性變數具有相同的作用域級別.這意味這匿名聯合內的成員的名稱不能與同乙個作用域內的其他一直標誌符衝突.

對匿名聯合還存在如下限制:

因為匿名聯合不使用點運算子,所以包含在匿名聯合內的元素必須是資料,不允許有成員函式,也不能包含私有或受保護的成員。還有,全域性匿名聯合必須是靜態(static)的,否則就必須放在匿名名字空間中。

7、幾點需要討論的地方:

1)聯合裡面那些東西不能存放?

我們知道,聯合裡面的東西共享記憶體,所以靜態、引用都不能用,因為他們不可能共享記憶體。

2)類可以放入聯合嗎?

我們先看乙個例子:

class test

private:

int data;

};typedef union _test

ui; 

編譯通不過,為什麼呢?

因為聯合裡不允許存放帶有建構函式、析夠函式、複製拷貝操作符等的類,因為他們共享記憶體,編譯器無法保證這些物件不被破壞,也無法保證離開時呼叫析夠函式。

3)又是匿名惹的禍??

我們先看下一段**: 

class test

operator long() const

private:

enum type ;

union 

datatype;

type stype;

test(test&);

test& operator=(const test&);

};test::test(const char *p):stype

(string),datatype.ch(p)

test::test(int in):stype(int),datatype.l(i)

看出什麼問題了嗎?呵呵,編譯通不過。為什麼呢?難道datatype.ch(p)和datatype.l(i)有問題嗎?

哈哈,問題在哪呢?讓我們來看看構造test物件時發生了什麼,當建立test物件時,自然要呼叫其相應的建構函式,在建構函式中當然要呼叫其成員的建構函式,所以其要去呼叫datatype成員的建構函式,但是他沒有建構函式可呼叫,所以出

錯。注意了,這裡可並不是匿名聯合!因為它後面緊跟了個data!

4)如何有效的防止訪問出錯?

使用聯合可以節省記憶體空間,但是也有一定的風險:通過乙個不適當的資料成員獲取當前物件的值!例如上面的ch、i交錯訪問。

為了防止這樣的錯誤,我們必須定義乙個額外的物件,來跟蹤當前被儲存在聯合中的值得型別,我們稱這個額外的物件為:union的判別式。

乙個比較好的經驗是,在處理作為類成員的union物件時,為所有union資料型別提供一組訪問函式。

C 中union的使用

聯合 union 在c c 裡面見得並不多,但是在一些對記憶體要求特別嚴格的地方,聯合又是頻繁出現,那麼究竟什麼是聯合 怎麼去用 有什麼需要注意的地方呢?就這些問題,我試著做一些簡單的回答,裡面肯定還有不當的地方,歡迎指出!1 什麼是聯合?聯合 是一種特殊的類,也是一種構造型別的資料結構。在乙個 聯...

C 中union的使用

聯合 union 在c c 裡面見得並不多,但是在一些對記憶體要求特別嚴格的地方,聯合又是頻繁出現,那麼究竟什麼是聯合 怎麼去用 有什麼需要注意的地方呢?就這些問題,我試著做一些簡單的回答,裡面肯定還有不當的地方,歡迎指出!1 什麼是聯合?聯合 是一種特殊的類,也是一種構造型別的資料結構。在乙個 聯...

C中union的用法

union是一種 類似 與struct的聯合體,聯合的所有成員引用的是記憶體中的相同位置,以最大的成員的記憶體長度作為union的記憶體大小。union主要用來節省空間,預設的訪問許可權是公有的.include using namespace std union node t int c obj s...