摘要:我們知道結構體(struct)是一種構造型別或複雜型別,它可以包含多個型別不同的成員。在c語言中,還有另外一種和結構體非常類似的語法,叫做共用體(union),共用體(union)有時也被稱為聯合或者聯合體,這也是 union 這個單詞的本意。
結構體和共用體的區別在於:結構體的各個成員會占用不同的記憶體,互相之間沒有影響;而共用體的所有成員占用同一段記憶體,修改乙個成員會影響其餘所有成員。
結構體占用的記憶體大於等於所有成員占用的記憶體的總和(成員之間可能會因為記憶體對齊存在縫隙),共用體占用的記憶體等於最長的成員占用的記憶體。共用體使用了記憶體覆蓋技術,同一時刻只能儲存乙個成員的值,如果對新的成員賦值,就會把原來成員的值覆蓋掉。
union的定義格式為:
union 共用體名;
共用體也是一種自定義型別,可以通過它來建立變數,例如:
union data;
union data a, b, c;
上面是先定義共用體,再建立變數,也可以在定義共用體的同時建立變數:
union data a, b, c;
如果不再定義新的變數,也可以將共用體的名字省略:
union a, b, c;
共用體 data 中,成員 f 占用的記憶體最多,為 8 個位元組,所以 data 型別的變數(也就是 a、b、c)也占用 8 個位元組的記憶體。請看下面的演示:
#include union data;
int main()
執行結果:
4, 4
40, @, 40
39, 9, 39
2059, y, 2059
3e25ad54, t, ad54
這段**不但驗證了共用體的長度,還說明共用體成員之間會相互影響,修改乙個成員的值會影響其他成員。
要想理解上面的輸出結果,弄清成員之間究竟是如何相互影響的,就得了解各個成員在記憶體中的分布。以上面的 data 為例,各個成員在記憶體中的分布如下:
成員 n、ch、m 在記憶體中「對齊」到一頭,對 ch 賦值修改的是前乙個位元組,對 m 賦值修改的是前兩個位元組,對 n 賦值修改的是全部位元組。也就是說,ch、m 會影響到 n 的一部分資料,而 n 會影響到 ch、m 的全部資料。
上圖是在絕大多數 pc 機上的記憶體分布情況,如果是 51 微控制器,情況就會有所不同:
為什麼不同的機器會有不同的分布情況呢?這跟機器的儲存的大小端模式有關。
補充:union其對齊方式要適合其中所有的成員。
示例:
union u
;
上面的程式中的,s佔9位元組,n佔4位元組,d佔8位元組,因此其至少需9位元組的空間。然而其實際大小並不是9,用運算子sizeof測試其大小為16。
這是因為這裡存在位元組對齊的問題,9既不能被4整除,也不能被8整除。因此補充位元組到16,這樣就符合所有成員的自身對齊了。從這裡可以看出聯合體所佔的空間不僅取決於最寬成員,還跟所有成員有關係,即其大小必須滿足兩個條件:
大小足夠容納最寬的成員;大小能被其包含的所有基本資料型別的大小所整除。
C語言拾遺 C語言資料型別 列舉型別
摘要 變數的三個基本屬性為 作用域 鏈結屬性和儲存型別。這三個屬性決定變數的可視性和生命期。在c語言中,僅有4種基本資料型別 整型 浮點型 指標和聚合型別 如 陣列和結構體 所有其他的型別都是從這4種基本型別的某種組合派生而來。列舉是 c 語言中的一種基本資料型別,它可以讓資料更簡潔,更易讀。宣告為...
C語言拾遺
main函式引數 c語言規定main函式引數只能有兩個,習慣上這兩個引數寫成argc和argv。c語言還規定argc必須是整形變數,argv必須是指向字串的指標陣列。因此,main函式的函式頭應該寫為 main argc,argv int argc char argv 或者 main int arg...
C語言拾遺
保證某些全域性變數的常量性 c c 中不能通過變數來定義陣列 const int row 10 const int col 10 c define row 10 define col 10orenum c style型別轉換 new type expression static cast expre...