一文帶你認(rèn)識(shí)C語(yǔ)言的聯(lián)合體和枚舉
一.聯(lián)合體
1.聯(lián)合體的聲明
聯(lián)合體(Union) 是一種特殊的用戶自定義數(shù)據(jù)類(lèi)型,它允許在同一內(nèi)存位置存儲(chǔ)不同類(lèi)型的數(shù)據(jù),但同時(shí)只能存儲(chǔ)其中一個(gè)成員。聯(lián)合體的所有成員共享相同的內(nèi)存空間,因此聯(lián)合體的大小等于其最大成員的大小。
我們來(lái)看一下簡(jiǎn)單定義,有些類(lèi)似于結(jié)構(gòu)體.。
#include<stdio.h> union un { int age; char i; }; int main() { return 0; }
雖然說(shuō)結(jié)構(gòu)上有些類(lèi)似于結(jié)構(gòu)體,但是看特點(diǎn)的話,他兩各不相同,各有所長(zhǎng)。
2.聯(lián)合體的特點(diǎn)
(一)內(nèi)存共享
聯(lián)合體的所有成員共享同一塊內(nèi)存地址。意味著不論聯(lián)合體有多少成員,它們都會(huì)使用同一個(gè)存儲(chǔ)空間。只有一個(gè)成員可以在同一時(shí)刻存儲(chǔ)有效數(shù)據(jù)。
優(yōu)點(diǎn):這種特性使聯(lián)合體節(jié)省內(nèi)存,特別適合多個(gè)數(shù)據(jù)不會(huì)同時(shí)使用的場(chǎng)景。
我們來(lái)看一個(gè)例子:
#include<stdio.h> union un { int age; char i; }; int main() { union un u = { 0 }; u.age = 0x11223344; u.i = 0x55; return 0; }
我們按F10進(jìn)入逐過(guò)程:
查看內(nèi)存:可以看到u.i的0x55覆蓋了u.age的44
可以說(shuō)明他們的內(nèi)存是共享的?。。?/strong>
(二)大小等于最大成員的大小
聯(lián)合體的大小等于其最大成員的大小。雖然它可以有多個(gè)成員,但只會(huì)根據(jù)其中最大成員的大小來(lái)分配內(nèi)存。
我們看一下例子:
#include<stdio.h> union un { int age; char i; }; int main() { union un u = { 0 }; //計(jì)算一下聯(lián)合體的大小 printf("%zd", sizeof(u)); return 0; }
結(jié)果是:
解釋:int四個(gè)字節(jié),char一個(gè)字節(jié),顯然最大的是四個(gè)字節(jié)。聯(lián)合體的大小即最大成員的大小
另一特殊情況:
當(dāng)最大成員大小不是最大對(duì)齊數(shù)的整數(shù)倍的時(shí)候,就要對(duì)齊到最大對(duì)齊數(shù)的整數(shù)倍。
看一例子:
#include<stdio.h> union un { char name[10]; int age; }; int main() { union un u = { 0 }; printf("%zd", sizeof(u)); return 0; }
我們看一下結(jié)果:
可以看到聯(lián)合體的大小并不是最大成員的大小10(char1個(gè)字節(jié),1*10),是12(最大對(duì)齊數(shù)4,4的整數(shù)倍)
這里10個(gè)char類(lèi)型和int類(lèi)型就已經(jīng)占用14個(gè)字節(jié)了,但是結(jié)果是12個(gè)字節(jié),所以這里也能證明聯(lián)合體的特點(diǎn)內(nèi)存共享。
(三)一次只能使用一個(gè)成員
聯(lián)合體(union)的特性是一次只能有效使用一個(gè)成員,因?yàn)樗谐蓡T共享同一塊內(nèi)存。當(dāng)你向一個(gè)成員賦值時(shí),之前賦值的其他成員數(shù)據(jù)會(huì)被覆蓋。
其實(shí)也就是因?yàn)榱硪粋€(gè)特性內(nèi)存共享導(dǎo)致的
#include <stdio.h> #include <string.h> union MyUnion { int i; float f; char str[20]; }; int main() { union MyUnion u; // 設(shè)置整數(shù)值 u.i = 42; printf("設(shè)置整數(shù)后: u.i = %d\n", u.i); // 設(shè)置浮點(diǎn)數(shù)值,覆蓋整數(shù)值 u.f = 3.14; printf("設(shè)置浮點(diǎn)型之后: u.f = %.2f\n", u.f); // 整數(shù)值被覆蓋,無(wú)法正常讀取 printf("u.i (設(shè)置浮點(diǎn)型之后) = %d (corrupted)\n", u.i); // 設(shè)置字符串,覆蓋浮點(diǎn)數(shù)值 strcpy(u.str, "Hello"); printf("設(shè)置字符串后: u.str = %s\n", u.str); // 浮點(diǎn)數(shù)值被覆蓋,無(wú)法正常讀取 printf("u.f (設(shè)置字符串后) = %.2f (corrupted)\n", u.f); return 0; }
結(jié)果:
3.聯(lián)合體相比較于結(jié)構(gòu)體
(一)內(nèi)存分配
結(jié)構(gòu)體:
- 結(jié)構(gòu)體中的每個(gè)成員都有自己獨(dú)立的內(nèi)存空間。
- 結(jié)構(gòu)體的總大小等于所有成員大小的總和(加上可能的內(nèi)存對(duì)齊)。
- 成員的內(nèi)存布局是順序的,成員之間不會(huì)共享內(nèi)存
聯(lián)合體:
- 聯(lián)合體中的所有成員共享同一塊內(nèi)存。
- 聯(lián)合體的總大小等于其中最大成員的大小。
- 只能同時(shí)使用一個(gè)成員,存入一個(gè)成員的值會(huì)覆蓋其他成員。
(二)使用方式
結(jié)構(gòu)體:
- 結(jié)構(gòu)體可以同時(shí)使用多個(gè)成員。每個(gè)成員都有獨(dú)立的存儲(chǔ)空間,互不干擾。
- 適合用于描述包含多個(gè)相關(guān)數(shù)據(jù)的復(fù)雜對(duì)象。
(三)內(nèi)存布局對(duì)比
看看這兩個(gè)代碼內(nèi)存的占用
我們看一下內(nèi)存分布圖:
(四)總結(jié)
特性 | 結(jié)構(gòu)體 | 聯(lián)合體 |
內(nèi)存分配 | 每個(gè)成員都有獨(dú)立內(nèi)存,大小為所有成員之和。 | 所有成員共享同一塊內(nèi)存,大小為最大成員。 |
使用多個(gè)成員 | 可以同時(shí)使用多個(gè)成員。 | 一次只能使用一個(gè)成員,修改會(huì)覆蓋其他成員。 |
適用場(chǎng)景 | 同時(shí)需要存儲(chǔ)和操作多種數(shù)據(jù)類(lèi)型。 | 不同時(shí)間只需使用一種數(shù)據(jù)類(lèi)型,節(jié)省內(nèi)存。 |
訪問(wèn)速度 | 各成員獨(dú)立訪問(wèn),互不影響。 | 需要判斷當(dāng)前存儲(chǔ)的成員類(lèi)型,可能增加復(fù)雜度。 |
二.枚舉
枚舉(enum)是一種用戶自定義的數(shù)據(jù)類(lèi)型,它由一組具名的常量組成。枚舉常用于表示一組相關(guān)的離散值,賦予這些值易于理解的名稱,增強(qiáng)代碼的可讀性和維護(hù)性。
1.特點(diǎn)
- 命名常量:枚舉為一組常量提供了有意義的名字,使代碼更具可讀性。
- 整數(shù)值:在大多數(shù)編程語(yǔ)言中,枚舉中的每個(gè)常量值都與一個(gè)整數(shù)值對(duì)應(yīng),通常從
0
開(kāi)始遞增,除非顯式指定。- 類(lèi)型安全:枚舉類(lèi)型可以幫助確保在代碼中只能使用有效的枚舉常量,而不會(huì)混用其他不相關(guān)的值。
2.語(yǔ)法
看個(gè)例子:
#include <stdio.h> enum Weekday { SUNDAY, // 默認(rèn)值為 0 MONDAY, // 1 TUESDAY, // 2 WEDNESDAY, // 3 THURSDAY, // 4 FRIDAY, // 5 SATURDAY // 6 }; int main() { enum Weekday today; today = WEDNESDAY; if (today == WEDNESDAY) { printf("Today is Wednesday!\n"); } return 0; }
結(jié)果如圖:
第二個(gè)例子(如果對(duì)某個(gè)成員賦值,后續(xù)成員會(huì)從該值開(kāi)始遞增):
enum EnumName { ENUM_VALUE1, //0 ENUM_VALUE2, //1 ENUM_VALUE3 = 10, // 可以顯式指定值 ENUM_VALUE4 // 之后的值會(huì)遞增,即11 };
枚舉中的每個(gè)常量值都與一個(gè)整數(shù)值對(duì)應(yīng),通常從
0
開(kāi)始遞增,除非顯式指定。
ps:要注意每個(gè)成員用","隔開(kāi)
3.特殊情況
(一)枚舉類(lèi)型的隱式轉(zhuǎn)換
枚舉類(lèi)型在 C 語(yǔ)言中實(shí)際上是整型,可能導(dǎo)致與整型混淆。比如,可以將整型值賦給枚舉類(lèi)型:
enum Weekday { SUNDAY, MONDAY, TUESDAY }; enum Weekday day = 3; // 這是合法的,但不安全
(二)枚舉的作用域
在 C 語(yǔ)言中,枚舉的常量在枚舉定義的作用域內(nèi)可見(jiàn),但不會(huì)限定在枚舉類(lèi)型內(nèi)部:
enum Colors { RED, GREEN, BLUE }; int color = RED; // 合法,因?yàn)?RED 在全局作用域中可見(jiàn)
(三)缺乏類(lèi)型安全
盡管枚舉在一定程度上提供了類(lèi)型安全,但它們的整型本質(zhì)仍然使得在比較或賦值時(shí)存在風(fēng)險(xiǎn)。例如,可以將一個(gè)枚舉類(lèi)型的變量賦值為與之不相關(guān)的整數(shù)值,這可能導(dǎo)致邏輯錯(cuò)誤:
enum Direction { NORTH, SOUTH, EAST, WEST }; enum Direction dir = 10; // 合法,但不正確
(四)枚舉的拓展
在 C 語(yǔ)言中,枚舉類(lèi)型一旦定義就不能被擴(kuò)展或修改。它的值和成員是固定的。因此,枚舉不能如同其他數(shù)據(jù)類(lèi)型那樣進(jìn)行動(dòng)態(tài)修改。
總結(jié)
到此這篇關(guān)于C語(yǔ)言聯(lián)合體和枚舉的文章就介紹到這了,更多相關(guān)C語(yǔ)言聯(lián)合體和枚舉內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C語(yǔ)言編程中的聯(lián)合體union入門(mén)學(xué)習(xí)教程
- C語(yǔ)言中聯(lián)合體union的實(shí)例詳解
- C語(yǔ)言中枚舉與聯(lián)合體的使用方法(enum union)
- C語(yǔ)言結(jié)構(gòu)體,枚舉,聯(lián)合體詳解
- C語(yǔ)言關(guān)于自定義數(shù)據(jù)類(lèi)型之枚舉和聯(lián)合體詳解
- C語(yǔ)言超詳細(xì)講解結(jié)構(gòu)體與聯(lián)合體的使用
- C語(yǔ)言枚舉與聯(lián)合體深入詳解
- C語(yǔ)言中聯(lián)合體與共用體和枚舉使用語(yǔ)法示例
- c語(yǔ)言中聯(lián)合體和枚舉用法詳解
- C語(yǔ)言聯(lián)合體類(lèi)型的實(shí)現(xiàn)
- C語(yǔ)言聯(lián)合體的實(shí)現(xiàn)示例
相關(guān)文章
C/C++實(shí)現(xiàn)通訊錄管理系統(tǒng)(附源碼)
這篇文章主要為大家詳細(xì)介紹了如何利用C++實(shí)現(xiàn)通訊錄管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-12-12windows下vscode環(huán)境c++利用matplotlibcpp繪圖
本文主要介紹了windows下vscode環(huán)境c++利用matplotlibcpp繪圖,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02OpenCV 圖像拼接和圖像融合的實(shí)現(xiàn)
本文主要介紹了OpenCV 圖像拼接和圖像融合,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08仿寫(xiě)C語(yǔ)言string.h頭文件檢驗(yàn)字符串函數(shù)
這里給大家分享的是一個(gè)C語(yǔ)言string.h頭文件檢驗(yàn)字符串函數(shù)的仿寫(xiě),非常的簡(jiǎn)單實(shí)用,小編覺(jué)得這篇文寫(xiě)的還不錯(cuò),希望能夠給你帶來(lái)幫助2021-11-11c++連接mysql5.6的出錯(cuò)問(wèn)題總結(jié)
下面小編就為大家?guī)?lái)一篇c++連接mysql5.6的出錯(cuò)問(wèn)題總結(jié)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧,祝大家游戲愉快哦2016-12-12C/C++哈希表優(yōu)化LeetCode題解997找到小鎮(zhèn)的法官
這篇文章主要為大家介紹了C/C++哈希表優(yōu)化題解997找到小鎮(zhèn)的法官示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12C++?qt實(shí)現(xiàn)打開(kāi)關(guān)閉狀態(tài)按鈕的代碼
這篇文章主要介紹了C++?qt實(shí)現(xiàn)打開(kāi)關(guān)閉狀態(tài)按鈕,用QCheckBox可以實(shí)現(xiàn),只要在選擇與未選擇的狀態(tài)設(shè)置不同的圖片即可完成,代碼簡(jiǎn)單易懂,需要的朋友可以參考下2022-03-03C++ read函數(shù)讀入int整形數(shù)據(jù)
這篇文章主要介紹了C++ read函數(shù)讀入int整形數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下2016-07-07