C C 中的那些不同 結構體和聯合體

2021-07-29 22:25:43 字數 2139 閱讀 7200

c和c++中有兩種從名字上看好像很有聯絡很相似的關鍵字,分別是結構體(struct),聯合體(union)。兩者的功能都是可以自定義資料型別,但是深層的原理是不一樣的。

看下如下結構體

struct test;

//sizeof(test) = 16

乙個test結構體的物件的大小為16位元組,而不是我們所認為的13(1+4+8)位元組。具體的原因是因為,為了讓cpu匯流排(32位或64位)的讀取效率達到最高,減少對記憶體的讀取次數,一般編譯器會對結構體的成員進行位元組對齊。預設要求符合

以下對齊的規則:

①對齊後的結構體變數的大小須為最寬位成員的整數倍。

②結構體每個成員相對結構體首位址的偏移量(offset)都是每個成員本身大小的整數倍(成員的首位址相對於結構體的首位址的偏移)

③如果成員也是乙個結構體,則結構體成員開始儲存的偏移要是該結構體成員中最大成員的整數倍。

%=非對齊的位元組

#=對齊插入的位元組

所以test的成員的大小的真實分布

|a|b|c| ->|%###|%%%%|%%%%%%%%|

偏移從0開始算第乙個%的偏移為0。

再來兩個例子

struct test2 ;

//sizeof(test2) = 24

struct test3 ;

//sizeof(test3)=24

可以發現,兩個例子的大小都是24,why? test3的物件的大小不應該是24吧。

我們下面來分解以下記憶體的真實分布

test2(很簡單)

|text|number1|number2| —-> |%%%%%###|%%%%####|%%%%%%%%|

當char插入5個位元組後,因為偏移6~7都不是第二個成員number1的型別long(4位元組)的整數倍,所以補齊了三個位元組,知道第8個偏移才是number1的資料存放位置。

然後呢因為偏移12~15也不是number2的大小(8位元組)的整數倍,所以補齊4個位元組,知道偏移16開始才是number2的資料存放位置。

所以最終的大小為:(4+3)+(4+4)+8 = 24。

可以發現也滿足對齊規則①

理解了test2後

test3(就要分析一下了)

|text|number2|number1| —-> |%%######|%%%%%%%%|%%%%####|

給char分配完了空間後,因為偏移2~7都不是longlong型別(8位元組)的大小的整數倍所以補齊6個位元組,在偏移8開始是number2的空間,然後剛好偏移16是long(4位元組)的大小的整數倍,所以偏移16開始是存放number1的空間。然後計算一下發現此時結構體的整體大小為:(2+6)+8+4=20。

20無法整除8,不滿足規則①,所以會繼續補齊,補4個位元組,直到結構體的整體大小為24,能夠整除8為止。這個就是要注意的了。

如果有成員是乙個結構體的話。

struct test2 ;

struct test1 ;

//大小為24,記憶體分布可以按照上面的規則畫畫。

聯合體就不同了。

對於①,其實就是聯合體的所有成員是共享記憶體的

比如

union test_u;

//sizeof(test_u) = 4

也就是說,聯合體如果對其中任意乙個成員賦值,是會發生覆蓋的。如果先給a賦值,然後在給b賦值。則a的資料會給覆蓋掉。

對於②就沒什麼問題的了。

但是③呢,就有點意思了,聯合體會發生對齊,且要適合全部成員?什麼意思

看看下面的例子

union test_u;

//sizeof(test_u) = 12

所以記憶體的分布為:

|a|b| —> |%%%%%%%%%###|

按照①和②的規則,test_u的大小應該是9位元組就足夠了,但是實際的大小為12。這是因為9只能整除char(1位元組)的大小,而無法整除int(4位元組)。所以發生了位元組對齊,差多了三個位元組,使得test_u的大小為12,以滿足③的要求。

在來乙個例子

union test_u;
大小為16位元組,根據條件來畫畫記憶體的分布唄。

結構體和聯合體

結構體是一些值的集合,這些值成為它的成員。這和陣列有些類似。結構體和陣列最大的不同是,陣列的元素都是相同型別的,而結構體裡的成員可以具有不同的型別。陣列元素可以通過下標來訪問,而結構體成員長度可能不同,所以不能通過下標訪問。每個結構體成員都有自己的名字,所以結構體成員是通過名字訪問的。結構體變數屬於...

聯合體和結構體

一 前言 聯合體 union 與 結構體 struct 有一些相似之處。但兩者有本質上的不同。在結構體中,各成員有各自的記憶體空間,乙個結構變數的總長度是各成員長度之和 而在 聯合 中,各成員共享一段記憶體空間,乙個聯合變數的長度等於各成員中最長的長度 應該說明的是,這裡所謂的共享不是指把多個成員同...

結構體聯合體

在c中,結構也是一種資料型別,可以使用結構變數,因此,象其它型別的變數一樣,在使用結構變數時要先對其定義。定義結構變數的一般格式為 struct 結構名 結構變數 結構名是結構的識別符號不是變數名。型別為第二節中所講述的五種資料型別 整型 浮點型 字元型 指標型和無值型 構成結構的每乙個型別變數稱為...