【C语言】自定义类型之联合和枚举
- 人工智能
- 2025-07-21 19:10:03

目录 1. 前言2. 联合体2.1 联合体类型的声明2.2 联合体的特点2.3 相同成员的结构体和联合体对比2.4 联合体大小的计算2.4 判断当前机器的大小端 3. 枚举3.1 枚举类型的声明3.2 枚举类型的优点3.3 枚举类型的使用 1. 前言
在之前的博客中介绍了自定义类型中的结构体,有想了解的可以点这个链接:link 今天来分享另外两种类型:联合和枚举。
2. 联合体 2.1 联合体类型的声明像结构体一样,联合体也是由一个或者多个成员构成,这些成员可以不同的类型。但是编译器只为最大的成员分配足够的内存空间。 联合体的特点是所有成员共用同一块内存空间。所以联合体也叫:共用体。
-----------------------------------------------------------------------------------------
我们举个例子来看一下:
我们发现在联合体中的大小占4个字节,这是为什么呢?
我们来看看它每个成员的地址 我们发现那三个的地址都是一样的。 改到32位平台上发现内存地址还是一样的。 也就是说它们共用一块空间
-----------------------------------------------------------------------------------------
给联合体其中⼀个成员赋值,其他成员的值也跟着变化。 在同一个时间点只能使用一个联合体成员。
2.2 联合体的特点联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合⾄少得有能力保存最大的那个成员)。
来看个例子
#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; }我们来看看在内存中的变换: 代码的输出,我们发现将i的第4个字节的内容修改为55了。 我们仔细分析就可以画出,un的内存布局图。
2.3 相同成员的结构体和联合体对比我们再对比一下相同成员的结构体和联合体的内存布局情况
结构体的代码:
struct S { char c; int i; }; struct S s = {0};联合体的代码:
union Un { char c; int i; }; union Un un = {0};对于结构体来说就占了8个字节,浪费了3个字节,而联合体占了4个字节。
2.4 联合体大小的计算当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
举个例子:计算下面两个联合体的大小?
#include <stdio.h> union Un1 { char c[5];//5 1 8 1 int i;//4 4 8 4 }; union Un2 { short c[7];//14 2 8 2 int i;//4 4 8 4 }; int main() { printf("%d\n", sizeof(union Un1));//8 printf("%d\n", sizeof(union Un2));//16 return 0; }对于Un1,char c[5],占五个字节,char类型占1个字节,对齐数默认是8,对比之后取对齐数取1。 int i,占4个字节,对齐数默认是8,对比之后取对齐数取4。所以等于5时,5不是4的倍数,就得浪费3个字节,取8。
对于Un2 ,short c[7]占14个字节,short占2个,对齐数默认是8,对比之后取对齐数取2; int i,占4个字节,对齐数默认是8,对比之后取对齐数取4。所以等于14时,14不是4的倍数,就得浪费2个字节,取16。
联合体的大小,并不是其中最大成员的大小
-----------------------------------------------------------------------------------------
使用联合体是可以节省空间的, 举例:
比如,我们要搞一个活动,要上线一个礼品兑换单,礼品兑换单中有三种商品:图书、杯子、衬衫。 每⼀种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。
图书:书名、作者、页数 杯子:设计 衬衫:设计、可选颜⾊、可选尺寸
如果我们使用结构体来定义这个活动的礼物时,
代码如下:
struct gift_list { //公共属性 int stock_number;//库存量 double price; //定价 int item_type;//商品类型 //特殊属性 char title[20];//书名 char author[20];//作者 int num_pages;//⻚数 char design[30];//设计 int colors;//颜⾊ int sizes;//尺⼨ };上述的结构其实设计的很简单,用起来也方便,但是结构的设计中包含了所有礼品的各种属性,这样使得结构体的大小就会偏大,比较浪费内存。因为对于礼品兑换单中的商品来说,只有部分属性信息是常用的。
所以我们就可以把公共属性单独写出来,剩余属于各种商品本身的属性使用联合体起来,这样就可以介绍所需的内存空间,一定程度上节省了内存。 用联合体来实现,代码如下:
struct gift_list { int stock_number;//库存量 double price; //定价 int item_type;//商品类型 union { struct { char title[20];//书名 char author[20];//作者 int num_pages;//页数 }book; struct { char design[30];//设计 }mug; struct { char design[30];//设计 int colors;//颜色 int sizes;//尺寸 }shirt; }item; };这里使用了匿名结构体,这里的书、杯子和衬衫是不能同时存在的。就按照最大的结构体内存也就是书所占的大小来开辟空间,这样其它的也能放下。
我们就可以选择礼物及它的成员。
2.4 判断当前机器的大小端在之间博客中有说明,这里就不过多讲述,有需要的可以查看; link
之前所写的代码是利用指针来判断的:
int main() { int a = 1; if (*(char*)&a == 1) { printf("小端\n"); } else { printf("大端\n"); } return 0; }结果显示的是小端。
-----------------------------------------------------------------------------------------
这次我们使用联合体来判断
int check_sys() { union { char c; int i; }u; u.i = 1; return u.c; } int main() { if (check_sys() == 1) printf("小端\n"); else printf("大端\n"); return 0; }也就是来判断一下u.c存的是0还是1? 结果和上面一样,是小端存储
3. 枚举 3.1 枚举类型的声明枚举顾名思义就是一一列举。 把可能的取值一一列举。 比如我们现实生活中:
一周的星期一到星期日是有限的7天,可以一一列举 性别有:男、女、保密,也可以一一列举 月份有12个月,也可以一一列举 三原色,也是可以意义列举
这些数据的表示就可以使用枚举了。
enum Day { //列出的是枚举类型的可能取值 //这些列出的可能取值被称为:枚举常量 Mon, Tues, Wed, Thur, Fri, Sat, Sun }; enum Sex { MALE, FEMALE, SECRET }; enum Color//颜⾊ { RED, GREEN, BLUE };以上定义的 enum Day , enum Sex , enum Color 都是枚举类型。 {}中的内容是枚举类型的可能取值,也叫 枚举常量 。 这些可能取值都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值。
来看看日期的取值: 也就是:默认从0开始,依次递增1,一直到6。
当然在声明枚举类型的时候也可以赋初值。
enum Color//颜⾊ { RED = 2, GREEN = 4, BLUE = 8 }; int main() { printf("%d %d %d\n", RED, GREEN, BLUE); return 0; } 3.2 枚举类型的优点我们可以使用 #define 定义常量,为什么非要使用枚举? 枚举的优点:
增加代码的可读性和可维护性和#define定义的标识符比较枚举有类型检查,更加严谨。便于调试,预处理阶段会删除 #define 定义的符号使用方便,一次可以定义多个常量枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用举个例子:实现一个简单计算器 我们就能将加减乘除设置成枚举类型,这样在主函数中进行对应的操作时就会知道就行的是哪中计算。 这里只是简单举个例子说明一下枚举的优点,具体的函数大家可以自行修改。
void menu() { printf("*********************\n"); printf("*** 1.add 2.sub ***\n"); printf("*** 3.mul 4.div ***\n"); printf("*** 0.exit ***\n"); printf("*********************\n"); } enum Option { EXIT,//0 ADD,//1 SUB,//2 MUL,//3 DIV//4 }; int Add(int a, int b) { return a + b; } int Sub(int a, int b) { return a - b; } int Mul(int a, int b) { return a * b; } int Div(int a, int b) { return a / b; } int main() { int input = 0; int a = 0; int b = 0; do { menu(); printf("请选择:"); scanf("%d", &input); scanf("%d %d", &a,&b); switch (input) { case ADD: Add(a, b); break; case SUB: Sub(a, b); break; case MUL: Mul(a, b); break; case DIV: Div(a, b); break; default: break; } } while (input); return 0; } 3.3 枚举类型的使用 enum Color//颜色 { RED = 1, GREEN = 2, BLUE = 4 }; int main() { enum Color clr = GREEN;//使用枚举常量给枚举变量赋值 enum Color clr2 = 2; printf("%d\n", sizeof(clr));//4 return 0; }那是否可以拿整数给枚举变量赋值呢?在C语言中是可以的,但是C++是不行的,C++的类型检查比较严格。
有错误请指出,大家一起进步!
【C语言】自定义类型之联合和枚举由讯客互联人工智能栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“【C语言】自定义类型之联合和枚举”
下一篇
React组件生命周期