C語言編程中的聯(lián)合體union入門學(xué)習(xí)教程
聯(lián)合體(union)在C語言中是一個特殊的數(shù)據(jù)類型,能夠存儲不同類型的數(shù)據(jù)在同一個內(nèi)存位置??梢远x一個聯(lián)合體使用許多成員,但只有一個部件可以包含在任何時候給定的值。聯(lián)合體會提供使用相同的存儲器位置供多用途的有效方式。
定義聯(lián)合體
要定義聯(lián)合體,必須使用union語句很相似于定義結(jié)構(gòu)。聯(lián)合體聲明中定義了一個新的數(shù)據(jù)類型,程序不止一個成員。聯(lián)合體聲明的格式如下:
union [union tag] { member definition; member definition; ... member definition; } [one or more union variables];
union標(biāo)簽是可選的,每個成員的定義是一個正常的變量定義,如 int i; 和 float f; 或任何其他有效的變量的定義。在聯(lián)合體定義的結(jié)尾,最后分號之前,可以指定一個或多個變量的聯(lián)合,但它是可選的。這里定義一個名為數(shù)據(jù)聯(lián)合類型有三個成員 i, f, 和 str:
union Data { int i; float f; char str[20]; } data;
現(xiàn)在,數(shù)據(jù)類型的變量可以存儲的整數(shù),一個浮點數(shù),或字符的字符串。這意味著一個單可變結(jié)構(gòu)即相同的存儲單元可用于存儲多個類型的數(shù)據(jù)。可以使用任何內(nèi)置或用戶定義的數(shù)據(jù)類型根據(jù)需要在聯(lián)合里面。
通過union所占用的內(nèi)存將大到足以容納聯(lián)合體的最大成員。例如,在上面的例子中的數(shù)據(jù)類型將占用20個字節(jié)的存儲空間,因為這是通過文字串所占用的最大空間。以下將顯示由上述聯(lián)合共占用內(nèi)存大小的例子:
#include <stdio.h> #include <string.h> union Data { int i; float f; char str[20]; }; int main( ) { union Data data; printf( "Memory size occupied by data : %d ", sizeof(data)); return 0; }
讓我們編譯和運行上面的程序,這將產(chǎn)生以下結(jié)果:
Memory size occupied by data : 20
訪問聯(lián)合體成員
要訪問聯(lián)合體的任何成員,我們使用成員訪問運算符(.)。成員訪問運算符編碼為聯(lián)合體變量名和成員,訪問時使用union關(guān)鍵字定義聯(lián)合體類型的變量。以下為例子來解釋聯(lián)合體的用法:
#include <stdio.h> #include <string.h> union Data { int i; float f; char str[20]; }; int main( ) { union Data data; data.i = 10; data.f = 220.5; strcpy( data.str, "C Programming"); printf( "data.i : %d ", data.i); printf( "data.f : %f ", data.f); printf( "data.str : %s ", data.str); return 0; }
讓我們編譯和運行上面的程序,這將產(chǎn)生以下結(jié)果:
data.i : 1917853763 data.f : 4122360580327794860452759994368.000000 data.str : C Programming
在這里,我們可以看到,聯(lián)合體成員i 和f 值被損壞,因為分配給變量終值已占用的內(nèi)存位置,如果str成員的值被很好的打印的原因?,F(xiàn)在,讓我們來再一次看看同樣的例子,我們將使用一個變量在同一時間,它是聯(lián)合體的主要目的:
#include <stdio.h> #include <string.h> union Data { int i; float f; char str[20]; }; int main( ) { union Data data; data.i = 10; printf( "data.i : %d ", data.i); data.f = 220.5; printf( "data.f : %f ", data.f); strcpy( data.str, "C Programming"); printf( "data.str : %s ", data.str); return 0; }
讓我們編譯和運行上面的程序,這將產(chǎn)生以下結(jié)果:
data.i : 10 data.f : 220.500000 data.str : C Programming
這里,所有的成員都得到打印得非常好,因為一個部件被一次使用。
應(yīng)用場合
當(dāng)多個數(shù)據(jù)需要共享內(nèi)存或者多個數(shù)據(jù)每次只取其一時,可以利用聯(lián)合體(union)。在C Programming Language 一書中對于聯(lián)合體是這么描述的:
1)聯(lián)合體是一個結(jié)構(gòu);
2)它的所有成員相對于基地址的偏移量都為0;
3)此結(jié)構(gòu)空間要大到足夠容納最"寬"的成員;
4)其對齊方式要適合其中所有的成員;
下面解釋這四條描述:
由于聯(lián)合體中的所有成員是共享一段內(nèi)存的,因此每個成員的存放首地址相對于于聯(lián)合體變量的基地址的偏移量為0,即所有成員的首地址都是一樣的。為了使得所有成員能夠共享一段內(nèi)存,因此該空間必須足夠容納這些成員中最寬的成員。對于這句“對齊方式要適合其中所有的成員”是指其必須符合所有成員的自身對齊方式。
下面舉例說明:
如聯(lián)合體
union U { char s[9]; int n; double d; };
s占9字節(jié),n占4字節(jié),d占8字節(jié),因此其至少需9字節(jié)的空間。然而其實際大小并不是9,用運算符sizeof測試其大小為16.這是因為這里存在字節(jié)對齊的問題,9既不能被4整除,也不能被8整除。因此補充字節(jié)到16,這樣就符合所有成員的自身對齊了。從這里可以看出聯(lián)合體所占的空間不僅取決于最寬成員,還跟所有成員有關(guān)系,即其大小必須滿足兩個條件:1)大小足夠容納最寬的成員;2)大小能被其包含的所有基本數(shù)據(jù)類型的大小所整除。
測試程序:
/*測試聯(lián)合體 2011.10.3*/ #include <iostream> using namespace std; union U1 { char s[9]; int n; double d; }; union U2 { char s[5]; int n; double d; }; int main(int argc, char *argv[]) { U1 u1; U2 u2; printf("%d\n",sizeof(u1)); printf("%d\n",sizeof(u2)); printf("0x%x\n",&u1); printf("0x%x\n",&u1.s); printf("0x%x\n",&u1.n); printf("0x%x\n",&u1.d); u1.n=1; printf("%d\n",u1.s[0]); printf("%lf\n",u1.d); unsigned char *p=(unsigned char *)&u1; printf("%d\n",*p); printf("%d\n",*(p+1)); printf("%d\n",*(p+2)); printf("%d\n",*(p+3)); printf("%d\n",*(p+4)); printf("%d\n",*(p+5)); printf("%d\n",*(p+6)); printf("%d\n",*(p+7)); return 0; }
輸出結(jié)果為:
16 8 0x22ff60 0x22ff60 0x22ff60 0x22ff60 1 0.000000 1 0 0 0 48 204 64 0 請按任意鍵繼續(xù). . .
對于sizeof(u1)=16。因為u1中s占9字節(jié),n占4字節(jié),d占8字節(jié),因此至少需要9字節(jié)。其包含的基本數(shù)據(jù)類型為char,int,double分別占1,4,8字節(jié),為了使u1所占空間的大小能被1,4,8整除,則需填充字節(jié)以到16,因此sizeof(u1)=16.
對于sizeof(u2)=8。因為u2中s占5字節(jié),n占4字節(jié),d占8字節(jié),因此至少需要8字節(jié)。其包含的基本數(shù)據(jù)類型為char,int,double分別占1,4,8字節(jié),為了使u2所占空間的大小能被1,4,8整除,不需填充字節(jié),因為8本身就能滿足要求。因此sizeof(u2)=8。
從打印出的每個成員的基地址可以看出,聯(lián)合體中每個成員的基地址都相同,等于聯(lián)合體變量的首地址。
對u1.n=1,將u1的n賦值為1后,則該段內(nèi)存的前4個字節(jié)存儲的數(shù)據(jù)為00000001 00000000 00000000 00000000
因此取s[0]的數(shù)據(jù)表示取第一個單元的數(shù)據(jù),其整型值為1,所以打印出的結(jié)果為1.
至于打印出的d為0.000000愿意如下。由于已知該段內(nèi)存前4字節(jié)的單元存儲的數(shù)據(jù)為00000001 00000000 00000000 00000000,從上面打印結(jié)果48,204,64,0可以知道后面4個字節(jié)單元中的數(shù)據(jù)為00110000 11001100 01000000 00000000,因此其表示的二進(jìn) 制浮點數(shù)為
00000000 01000000 11001100 00110000 00000000 00000000 00000000 00000001
對于double型數(shù)據(jù),第63位0為符號位,62-52 00000000100為階碼,0000 11001100 00110000 00000000 00000000 00000000 00000001為尾數(shù),根據(jù)其值知道尾數(shù)值約為0,而階碼為4-1023=-1019,因此其表示的浮點數(shù)為1.0*2^(-1019)=0.00000000000......,因此輸出結(jié)果為0.000000。
欄 目:C語言
下一篇:基于C++實現(xiàn)kinect+opencv 獲取深度及彩色數(shù)據(jù)
本文標(biāo)題:C語言編程中的聯(lián)合體union入門學(xué)習(xí)教程
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/2612.html
您可能感興趣的文章
- 01-10深入Main函數(shù)中的參數(shù)argc,argv的使用詳解
- 01-10如何尋找數(shù)組中的第二大數(shù)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解
- 01-10深入C/C++浮點數(shù)在內(nèi)存中的存儲方式詳解
- 01-10深入探討C語言中局部變量與全局變量在內(nèi)存中的存放位置
- 01-10深入解析C中的數(shù)值與
- 01-10探討:程序在內(nèi)存中的分配(常量,局部變量,全局變量,程序代碼)問
- 01-10基于linux下C開發(fā)中的幾點技術(shù)經(jīng)驗總結(jié)
- 01-10淺析C語言中的sizeof


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機閱讀
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10delphi制作wav文件的方法
- 01-10C#中split用法實例總結(jié)
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-11ajax實現(xiàn)頁面的局部加載
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 04-02jquery與jsp,用jquery