目錄
前言
一、?聯合體類型的聲明
介紹:
注意:
二、?聯合體的特點
介紹:
代碼舉例:
三、聯合體??的計算
介紹:
聯合體大小的計算規則
1. 基礎規則
1. 確定最大成員大小
2. 計算對齊模數的最小公倍數
3. 最終大小
結論
關鍵總結
結論
四、枚舉類型的聲明
介紹:
五、枚舉類型的優點
介紹:
總結
前言
上一篇文章講解結構體類型的聲明、結構體變量的創建和初始化、結構成員訪問操作符、結構體內存對?知識的相關內容,本篇文章將講解聯合體類型的聲明、聯合體的特點、聯合體??的計算、枚舉類型的聲明、枚舉類型的優點、枚舉類型的使?知識的相關內容。
一、?聯合體類型的聲明
介紹:
在C語言中,聯合體(Union)?是一種特殊的數據類型,它允許在同一段內存空間中存儲不同類型的數據,但同一時刻只能保存其中一種類型的值。以下是聯合體類型的常見聲明方式:
union 聯合體標簽名 {成員類型1 成員名1;成員類型2 成員名2;// ... 其他成員
};
- 使用場景:聲明后可通過?
union 聯合體標簽名
?定義變量。
代碼例:
union Data {int num;float f;char str[20];
};
union Data data; // 定義聯合體變量
注意:
1.像結構體?樣,聯合體也是由?個或者多個成員構成,這些成員可以是不同的類型。
2.聯合體的關鍵字是union. 但是編譯器只為最?的成員分配?夠的內存空間。
3.聯合體的特點是所有成員共?同?塊內存空間。所 以聯合體也叫:共?體。 給聯合體其中?個成員賦值,其他成員的值也跟著變化。
二、?聯合體的特點
介紹:
聯合的成員是共?同?塊內存空間的,這樣?個聯合變量的??,?少是最?成員的??(因為聯合 ?少得有能?保存最?的那個成員)。
代碼舉例:
#include <stdio.h>
//聯合類型的聲明
union Un
{char c;int i;
};
int main()
{
//聯合變量的定義union Un un = {0};
//輸出的結果是?樣的嗎?printf("%p\n", &(un.i));printf("%p\n", &(un.c));printf("%p\n", &un);return 0;
}
由此我們可以得出聯合的成員是共?同?塊內存空間的,那么,改其中一個成員的地址,其他成員的地址受到影響嗎?
例:
#include <stdio.h>
//聯合類型的聲明
union Un
{char c;int i;
};
int main()
{
//聯合變量的定義union Un un = {0};un.i = 0x11223344;un.c = 0x55;printf("%x\n", un.i);return 0;
}
由代碼以及結果,我們可知:我們改其中一個成員的地址,其他成員的地址受到影響,通過改c,將i的第4個字節的內容修改為55了。
這處我們通過圖來講解:
詳細講解:
union Un
?包含?char c
(1字節)和?int i
(4字節),因此聯合體大小為?4字節(取最大成員?int
?的大小)。- 所有成員共用這4字節內存,
c
?存儲在內存的最低地址字節(取決于系統字節序,默認這是小端字節序,即低字節存低位數據)。初始賦值與修改過程
步驟1:
un.i = 0x11223344
在小端字節序下,4字節內存的存儲形式為(從低地址到高地址):
44
(0x44)、33
(0x33)、22
(0x22)、11
(0x11)。步驟2:
un.c = 0x55
char c
?會覆蓋內存中最低地址的1字節,將原?44
?替換為?55
。此時內存變為:
55
(0x55)、33
(0x33)、22
(0x22)、11
(0x11)。最終讀取?
un.i
?的值
內存中的4字節數據組合為?0x11223355
(高地址字節?11
?為最高位,低地址字節?55
?為最低位),因此?printf("%x\n", un.i)
?輸出?11223355
。
既然聯合體是公用內存,那我們來對??下相同成員的結構體和聯合體的內存布局情況。
先列出聯合體:
#include <stdio.h>
union Un
{char c;int i;
};
int main()
{ union Un un = {0};printf("%p\n", &(un.i));printf("%p\n", &(un.c));printf("%p\n", &un);return 0;
}
結構體:
#include <stdio.h>
struct s
{char c;int i;
};
int main()
{ struct s un = {0};printf("%p\n", &(un.i));printf("%p\n", &(un.c));printf("%p\n", &un);return 0;
}
結合圖:
三、聯合體??的計算
介紹:
聯合體計算大小和結構體相同,有內存對齊規則:
下面解釋一下:
聯合體大小的計算規則
聯合體(Union)的大小由最大成員的大小和內存對齊規則共同決定,核心原則是:聯合體的總大小必須能容納最大的成員,且滿足所有成員的對齊要求。
1. 基礎規則
- 取最大成員大小:聯合體的大小首先至少是所有成員中占用內存最大的那個成員的大小。
- 滿足內存對齊:最終大小需向上調整為所有成員對齊模數的最小公倍數的倍數(對齊模數通常為成員類型的大小,如
int
為4字節,double
為8字節等)。
列舉下例子:
union Test1 {char a; // 1字節int b; // 4字節double c; // 8字節
};
1. 確定最大成員大小
- 成員?
a
(char
):1字節- 成員?
b
(int
):4字節- 成員?
c
(double
):8字節- 最大成員大小 = 8字節(
double c
)。2. 計算對齊模數的最小公倍數
各成員的對齊數(通常為類型大小):
char
:1字節int
:4字節double
:8字節 (最?對?數)- 最小公倍數 = 8(1、4、8的最小公倍數為8)。
3. 最終大小
聯合體大小需滿足:
- 容納最大成員(8字節);
- 是對齊模數最小公倍數(8)的倍數。
因此,
union Test1
?的大小為 8字節??。結論
union Test1
?在內存中占用?8字節,由最大成員?double c
?的大小和對齊要求共同決定。
例:
#include <stdio.h>
union Un1
{char c[5];int i;
};
union Un2
{short c[7];int i;
};
int main()
{printf("%d\n", sizeof(union Un1));printf("%d\n", sizeof(union Un2));return 0;
}
接下來,將對其詳解:
union Un1
?的大小計算
- 最大成員大小:
char c[5]
?占5字節(大于?int i
?的4字節)。- 對齊模數:
char
?數組的對齊數 = 1字節(基礎類型?char
?的大小);int
?的對齊數 = 4字節。- 最小公倍數 =?4(1和4的最小公倍數)。
- 調整對齊:5字節需向上調整為4的倍數(5 → 8,因為 4×2=8)。
- 結果:
sizeof(union Un1) = 8
。2.?
union Un2
?的大小計算
- 最大成員大小:
short c[7]
?占14字節(大于?int i
?的4字節)。- 對齊模數:
short
?數組的對齊數 = 2字節(基礎類型?short
?的大小);int
?的對齊數 = 4字節。- 最小公倍數 =?4(2和4的最小公倍數)。
- 調整對齊:14字節需向上調整為4的倍數(14 → 16,因為 4×4=16)。
- 結果:
sizeof(union Un2) = 16
。關鍵總結
聯合體大小需同時滿足?“容納最大成員”?和?“對齊模數最小公倍數的倍數”?兩個條件,當最大成員大小不滿足對齊要求時,需向上補齊 💡。
注意:基礎類型?short
?的大小為2個字節。
當然,聯合體可以幫助我們解決很多問題,例如:求系統的大小端字節序:
如果不了解的可一看一下數據在內存中的存儲該章節內容。
#include <stdio.h>
union Un1
{int i;char c;};
int main()
{union Un1 a;a.i=1;a.c=*((char*)&a.i);if(a.c==1){printf("小端字節序\n");}else{printf("大端字節序\n");}return 0;
}
解釋:
- 聯合體成員共享同一塊內存空間,
i
?和?c
?的起始地址相同。char c
?僅訪問內存中?第一個字節?的數據。字節序判斷原理
a.i = 1
:將整數?1
?存入?int i
,其二進制表示為(假設32位系統):
00000000 00000000 00000000 00000001
(高位字節在前,低位字節在后)。字節序影響內存存儲:
- 小端字節序:低位字節存低地址 → 第一個字節為?
00000001
(值為1)。- 大端字節序:高位字節存低地址 → 第一個字節為?
00000000
(值為0)。
a.c = *((char*)&a.i)
:直接讀取?i
?的第一個字節數據到?c
。條件判斷結果
- 若?
a.c == 1
?→ 第一個字節為?1
?→?小端字節序。- 若?
a.c == 0
?→ 第一個字節為?0
?→?大端字節序。結論
程序通過聯合體共享內存的特性,讀取整數?
1
?的第一個字節數據,最終判斷當前系統為?小端字節序?💡。
四、枚舉類型的聲明
介紹:
枚舉顧名思義就是??列舉,把可能的取值??列舉。
代碼示例:
enum Color{RED,GREEN,BLUE
};
詳解:
默認值規則
- 首個常量默認值為?
0
,后續常量默認值為?前一個常量值 + 1。- 可通過?
=
?顯式指定任意整數(支持負數),未指定的后續常量自動遞增。
enum Color{RED=2,GREEN,BLUE
};
這樣實現。
五、枚舉類型的優點
介紹:
1. 增加代碼的可讀性和可維護性。
2. 和#define定義的標識符?較枚舉有類型檢查,更加嚴謹。
3. 便于調試,預處理階段會刪除 #define 定義的符號。
4. 使??便,?次可以定義多個常量。
5. 枚舉常量是遵循作?域規則的,枚舉聲明在函數內,只能在函數內使?。
使用示例:
#include <stdio.h>// 聲明并定義枚舉
typedef enum {SPRING = 1, // 顯式從1開始SUMMER, // 2AUTUMN, // 3WINTER // 4
} Season;int main() {Season s = SUMMER;printf("當前季節編號:%d\n", s); // 輸出:2return 0;
}
總結
?以上就是今天要講的內容,本文介紹了聯合體類型的聲明、聯合體的特點、聯合體??的計算、枚舉類型的聲明、枚舉類型的優點、枚舉類型的使?知識的相關內容,為本章節知識的內容,希望大家能喜歡我的文章,謝謝各位,同時自定義類型:結構體、聯合與枚舉部分也結束了,下篇文將為大家帶來新的知識。