C語(yǔ)言 共用體(Union)詳解及示例代碼
通過(guò)前面的講解,我們知道結(jié)構(gòu)體(Struct)是一種構(gòu)造類型或復(fù)雜類型,它可以包含多個(gè)類型不同的成員。在C語(yǔ)言中,還有另外一種和結(jié)構(gòu)體非常類似的語(yǔ)法,叫做共用體(Union),它的定義格式為:
union 共用體名{
成員列表
};
共用體有時(shí)也被稱為聯(lián)合或者聯(lián)合體,這也是 Union 這個(gè)單詞的本意。
結(jié)構(gòu)體和共用體的區(qū)別在于:結(jié)構(gòu)體的各個(gè)成員會(huì)占用不同的內(nèi)存,互相之間沒(méi)有影響;而共用體的所有成員占用同一段內(nèi)存,修改一個(gè)成員會(huì)影響其余所有成員。
結(jié)構(gòu)體占用的內(nèi)存大于等于所有成員占用的內(nèi)存的總和(成員之間可能會(huì)存在縫隙),共用體占用的內(nèi)存等于最長(zhǎng)的成員占用的內(nèi)存。共用體使用了內(nèi)存覆蓋技術(shù),同一時(shí)刻只能保存一個(gè)成員的值,如果對(duì)新的成員賦值,就會(huì)把原來(lái)成員的值覆蓋掉。
共用體也是一種自定義類型,可以通過(guò)它來(lái)創(chuàng)建變量,例如:
union data{ int n; char ch; double f; }; union data a, b, c;
上面是先定義共用體,再創(chuàng)建變量,也可以在定義共用體的同時(shí)創(chuàng)建變量:
union data{ int n; char ch; double f; } a, b, c;
如果不再定義新的變量,也可以將共用體的名字省略:
union data{ int n; char ch; double f; } a, b, c;
共用體 data 中,成員 f 占用的內(nèi)存最多,為 8 個(gè)字節(jié),所以 data 類型的變量(也就是 a、b、c)也占用 8 個(gè)字節(jié)的內(nèi)存,請(qǐng)看下面的演示:
#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; }
運(yùn)行結(jié)果:
4, 4
40, @, 40
39, 9, 39
2059, Y, 2059
3E25AD54, T, AD54
這段代碼不但驗(yàn)證了共用體的長(zhǎng)度,還說(shuō)明共用體成員之間會(huì)相互影響,修改一個(gè)成員的值會(huì)影響其他成員。
要想理解上面的輸出結(jié)果,弄清成員之間究竟是如何相互影響的,就得了解各個(gè)成員在內(nèi)存中的分布。以上面的 data 為例,各個(gè)成員在內(nèi)存中的分布如下:
成員 n、ch、m 在內(nèi)存中“對(duì)齊”到一頭,對(duì) ch 賦值修改的是前一個(gè)字節(jié),對(duì) m 賦值修改的是前兩個(gè)字節(jié),對(duì) n 賦值修改的是全部字節(jié)。也就是說(shuō),ch、m 會(huì)影響到 n 的一部分?jǐn)?shù)據(jù),而 n 會(huì)影響到 ch、m 的全部數(shù)據(jù)。
上圖是在絕大多數(shù) PC 機(jī)上的內(nèi)存分布情況,如果是 51 單片機(jī),情況就會(huì)有所不同:
為什么不同的機(jī)器會(huì)有不同的分布情況呢?這跟機(jī)器的存儲(chǔ)模式有關(guān),我們將在VIP教程《大端小端以及判別方式》一節(jié)中展開(kāi)探討。
共用體的應(yīng)用
共用體在一般的編程中應(yīng)用較少,在單片機(jī)中應(yīng)用較多。對(duì)于 PC 機(jī),經(jīng)常使用到的一個(gè)實(shí)例是: 現(xiàn)有一張關(guān)于學(xué)生信息和教師信息的表格。學(xué)生信息包括姓名、編號(hào)、性別、職業(yè)、分?jǐn)?shù),教師的信息包括姓名、編號(hào)、性別、職業(yè)、教學(xué)科目。請(qǐng)看下面的表格:
Name
|
Num
|
Sex
|
Profession
|
Score / Course
|
---|---|---|---|---|
HanXiaoXiao |
501
|
f
|
s
|
89.5
|
YanWeiMin |
1011
|
m
|
t
|
math
|
LiuZhenTao |
109
|
f
|
t
|
English
|
ZhaoFeiYan |
982
|
m
|
s
|
95.0
|
f 和 m 分別表示女性和男性,s 表示學(xué)生,t 表示教師??梢钥闯?,學(xué)生和教師所包含的數(shù)據(jù)是不同的?,F(xiàn)在要求把這些信息放在同一個(gè)表格中,并設(shè)計(jì)程序輸入人員信息然后輸出。
如果把每個(gè)人的信息都看作一個(gè)結(jié)構(gòu)體變量的話,那么教師和學(xué)生的前 4 個(gè)成員變量是一樣的,第 5 個(gè)成員變量可能是 score 或者 course。當(dāng)?shù)?4 個(gè)成員變量的值是 s 的時(shí)候,第 5 個(gè)成員變量就是 score;當(dāng)?shù)?4 個(gè)成員變量的值是 t 的時(shí)候,第 5 個(gè)成員變量就是 course。
經(jīng)過(guò)上面的分析,我們可以設(shè)計(jì)一個(gè)包含共用體的結(jié)構(gòu)體,請(qǐng)看下面的代碼:
#include <stdio.h> #include <stdlib.h> #define TOTAL 4 //人員總數(shù) struct{ char name[20]; int num; char sex; char profession; union{ float score; char course[20]; } sc; } bodys[TOTAL]; int main(){ int i; //輸入人員信息 for(i=0; i<TOTAL; i++){ printf("Input info: "); scanf("%s %d %c %c", bodys[i].name, &(bodys[i].num), &(bodys[i].sex), &(bodys[i].profession)); if(bodys[i].profession == 's'){ //如果是學(xué)生 scanf("%f", &bodys[i].sc.score); }else{ //如果是老師 scanf("%s", bodys[i].sc.course); } fflush(stdin); } //輸出人員信息 printf("\nName\t\tNum\tSex\tProfession\tScore / Course\n"); for(i=0; i<TOTAL; i++){ if(bodys[i].profession == 's'){ //如果是學(xué)生 printf("%s\t%d\t%c\t%c\t\t%f\n", bodys[i].name, bodys[i].num, bodys[i].sex, bodys[i].profession, bodys[i].sc.score); }else{ //如果是老師 printf("%s\t%d\t%c\t%c\t\t%s\n", bodys[i].name, bodys[i].num, bodys[i].sex, bodys[i].profession, bodys[i].sc.course); } } return 0; }
運(yùn)行結(jié)果:
Input info: HanXiaoXiao 501 f s 89.5↙
Input info: YanWeiMin 1011 m t math↙
Input info: LiuZhenTao 109 f t English↙
Input info: ZhaoFeiYan 982 m s 95.0↙
Name Num Sex Profession Score / Course
HanXiaoXiao 501 f s 89.500000
YanWeiMin 1011 m t math
LiuZhenTao 109 f t English
ZhaoFeiYan 982 m s 95.000000
以上就是對(duì) C語(yǔ)言共用體 的資料整理,后續(xù)繼續(xù)補(bǔ)充相關(guān)資料,謝謝大家對(duì)本站的支持!
相關(guān)文章
C語(yǔ)言-I/O流設(shè)計(jì)實(shí)驗(yàn)
編程語(yǔ)言的I/O類庫(kù)中常常使用流這個(gè)抽象的概念,它代表任何有能力產(chǎn)生數(shù)據(jù)的數(shù)據(jù)源對(duì)象或時(shí)有能力接收數(shù)據(jù)的接收端對(duì)象,本文為大家介紹C語(yǔ)言中I/O系統(tǒng)基礎(chǔ)知識(shí)2021-07-07嵌入式C程序優(yōu)質(zhì)編寫(xiě)全面教程規(guī)范
這是一年前我為公司內(nèi)部寫(xiě)的一個(gè)文檔,旨在向年輕的嵌入式軟件工程師們介紹如何在裸機(jī)環(huán)境下編寫(xiě)優(yōu)質(zhì)嵌入式C程序。感覺(jué)是有一定的參考價(jià)值,所以拿出來(lái)分享,拋磚引玉2022-04-04c語(yǔ)言如何設(shè)置隨機(jī)數(shù)及逐行解析
在C語(yǔ)言中,rand()函數(shù)可以用來(lái)產(chǎn)生隨機(jī)數(shù),但是這不是真真意義上的隨機(jī)數(shù),是一個(gè)偽隨機(jī)數(shù),下面這篇文章主要給大家介紹了關(guān)于c語(yǔ)言如何設(shè)置隨機(jī)數(shù)及逐行解析的相關(guān)資料,需要的朋友可以參考下2022-11-11C/C++實(shí)現(xiàn)枚舉網(wǎng)上鄰居信息的示例詳解
在Windows系統(tǒng)中,通過(guò)網(wǎng)絡(luò)鄰居可以方便地查看本地網(wǎng)絡(luò)中的共享資源和計(jì)算機(jī),本文將介紹一個(gè)簡(jiǎn)單的C++程序,使用Windows API枚舉網(wǎng)絡(luò)鄰居信息,并獲取對(duì)端名稱、本機(jī)名稱、主機(jī)名稱以及主機(jī)IP等信息,文中通過(guò)代碼示例給大家講解非詳細(xì),需要的朋友可以參考下2023-12-12