C 語(yǔ)言關(guān)于聯(lián)合體的相關(guān)知識(shí)
當(dāng)多個(gè)數(shù)據(jù)需要共享內(nèi)存或者多個(gè)數(shù)據(jù)每次只取其一時(shí),可以利用聯(lián)合體(union)。在C Programming Language 一書中對(duì)于聯(lián)合體是這么描述的:
1)聯(lián)合體是一個(gè)結(jié)構(gòu);
2)它的所有成員相對(duì)于基地址的偏移量都為0;
3)此結(jié)構(gòu)空間要大到足夠容納最"寬"的成員;
4)其對(duì)齊方式要適合其中所有的成員;
下面解釋這四條描述:
由于聯(lián)合體中的所有成員是共享一段內(nèi)存的,因此每個(gè)成員的存放首地址相對(duì)于于聯(lián)合體變量的基地址的偏移量為0,即所有成員的首地址都是一樣的。為了使得所有成員能夠共享一段內(nèi)存,因此該空間必須足夠容納這些成員中最寬的成員。對(duì)于這句“對(duì)齊方式要適合其中所有的成員”是指其必須符合所有成員的自身對(duì)齊方式。
下面舉例說(shuō)明:
如聯(lián)合體
union U { char s[9]; int n; double d; };
s占9字節(jié),n占4字節(jié),d占8字節(jié),因此其至少需9字節(jié)的空間。然而其實(shí)際大小并不是9,用運(yùn)算符sizeof測(cè)試其大小為16.這是因?yàn)檫@里存在字節(jié)對(duì)齊的問(wèn)題,9既不能被4整除,也不能被8整除。因此補(bǔ)充字節(jié)到16,這樣就符合所有成員的自身對(duì)齊了。從這里可以看出聯(lián)合體所占的空間不僅取決于最寬成員,還跟所有成員有關(guān)系,即其大小必須滿足兩個(gè)條件:
1)大小足夠容納最寬的成員;
2)大小能被其包含的所有基本數(shù)據(jù)類型的大小所整除。
測(cè)試程序:
/*測(cè)試聯(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
對(duì)于sizeof(u1)=16。因?yàn)閡1中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.
對(duì)于sizeof(u2)=8。因?yàn)閡2中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é),因?yàn)?本身就能滿足要求。因此sizeof(u2)=8。
從打印出的每個(gè)成員的基地址可以看出,聯(lián)合體中每個(gè)成員的基地址都相同,等于聯(lián)合體變量的首地址。
對(duì)u1.n=1,將u1的n賦值為1后,則該段內(nèi)存的前4個(gè)字節(jié)存儲(chǔ)的數(shù)據(jù)為00000001 00000000 00000000 00000000
因此取s[0]的數(shù)據(jù)表示取第一個(gè)單元的數(shù)據(jù),其整型值為1,所以打印出的結(jié)果為1.
至于打印出的d為0.000000愿意如下。由于已知該段內(nèi)存前4字節(jié)的單元存儲(chǔ)的數(shù)據(jù)為00000001 00000000 00000000 00000000,從上面打印結(jié)果48,204,64,0可以知道后面4個(gè)字節(jié)單元中的數(shù)據(jù)為00110000 11001100 01000000 00000000,因此其表示的二進(jìn) 制浮點(diǎn)數(shù)為
00000000 01000000 11001100 00110000 00000000 00000000 00000000 00000001
對(duì)于double型數(shù)據(jù),第63位0為符號(hào)位,62-52 00000000100為階碼,0000 11001100 00110000 00000000 00000000 00000000 00000001為尾數(shù),根據(jù)其值知道尾數(shù)值約為0,而階碼為4-1023=-1019,因此其表示的浮點(diǎn)數(shù)為1.0*2^(-1019)=0.00000000000......,因此輸出結(jié)果為0.000000。
以上就是C 語(yǔ)言關(guān)于聯(lián)合體的相關(guān)知識(shí)的詳細(xì)內(nèi)容,更多關(guān)于C語(yǔ)言 聯(lián)合體的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++ 詳細(xì)講解stack與queue的模擬實(shí)現(xiàn)
C++ Stack(堆棧) 是一個(gè)容器類的改編,為程序員提供了堆棧的全部功能,也就是說(shuō)實(shí)現(xiàn)了一個(gè)先進(jìn)后出(FILO)的數(shù)據(jù)結(jié)構(gòu),許多程序都使用了 queue 容器。queue 容器可以用來(lái)表示超市的結(jié)賬隊(duì)列或服務(wù)器上等待執(zhí)行的數(shù)據(jù)庫(kù)事務(wù)隊(duì)列2022-04-04C++ Boost實(shí)現(xiàn)異步端口掃描器詳解
端口掃描是一種用于識(shí)別目標(biāo)系統(tǒng)上哪些網(wǎng)絡(luò)端口處于開(kāi)放、關(guān)閉或監(jiān)聽(tīng)狀態(tài)的網(wǎng)絡(luò)活動(dòng),本文將運(yùn)用Boost框架實(shí)現(xiàn)一個(gè)基于TCP的掃描工具,有需要的小伙伴可以參考下2023-11-11C語(yǔ)言獲取Linux系統(tǒng)精確時(shí)間的方法
下面小編就為大家?guī)?lái)一篇C語(yǔ)言獲取Linux系統(tǒng)精確時(shí)間的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09C語(yǔ)言調(diào)試手段:鎖定錯(cuò)誤的實(shí)現(xiàn)方法
本篇文章是對(duì)在C語(yǔ)言調(diào)試中,鎖定錯(cuò)誤的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05解決C++ openCV無(wú)法讀取視頻但是可以讀取圖像的問(wèn)題記錄
在使用OpenCV的cv::VideoCapture讀取視頻文件時(shí),可能會(huì)遇到無(wú)法讀取特定格式,如MP4的視頻文件的問(wèn)題,本文介紹解決C++ openCV無(wú)法讀取視頻但是可以讀取圖像的問(wèn)題記錄,感興趣的朋友跟隨小編一起看看吧2024-09-09詳解C語(yǔ)言動(dòng)態(tài)內(nèi)存的分配
這篇文章主要為大家介紹了C語(yǔ)言動(dòng)態(tài)內(nèi)存的分配,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2021-12-12