当前位置: 首页 > news >正文

C语言-自定义类型:联合和枚举

1.枚举

1.1枚举类型的声明

枚举顾名思义就是一一列举

把可能的值一一列举出来

例如:一周的星期,性别,月份等等

枚举的关键字:enum

enum day
{
	mon,
	tues,
	wed,
	thur,
	fri,
	sat,
	sun,
};
enum sex
{
	male,
	female,
	secret
 };

上述是关于星期和性别的枚举声明定义

{}中的内从是枚举类型的可能取值,也叫做枚举常量

枚举常量的默认值是从0开始依次递增

所以fri和male的值是4和0

而且枚举常量的默认值是可以修改的,但是只能在定义中进行默认值的初始化,在main中也不能修改

图中可得在定义中对wed的默认值进行了修改,改成了5,所以fri的值就从5开始依次加1变成了7,而tues还是从0开始加1,所以是1

2.2枚举类型的优点

其实我们可以使用#define定义常量,为什么非要用枚举?

1.增加代码的可读性和可维护性

2.和#define定义的标识符比较枚举有类型检查,更加严谨(例如C++中就会出现问题)

3.便于调试,预处理阶段会删除#define定义的符号

4.使用方便,一次可以定义多个常量

5.枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用

2.3枚举类型的使用

enum Color//颜⾊
{
	RED = 1,
	GREEN = 2,
	BLUE = 4
};
enum Color clr = GREEN;//使⽤枚举常量给枚举变量赋值

是否可以拿整数给枚举变量赋值呢?在C语言中可以,但是C++中不行,C++的类型检查严格。

枚举使用的例子(计算加减乘除的计算器):

//枚举应用的例子
//计算器(加减乘除)
void menu()
{
	printf("**请输入选择**\n");
	printf("**  1. add  **\n");
	printf("**  2. sub  **\n");
	printf("**  3. mul  **\n");
	printf("**  4. div  **\n");
	printf("**  0. exit **\n");
}
int main()
{
	int input = 0;
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			break;
		case 2:
			break;
		case 3:
			break;
		case 4:
			break;
		case 0:
			printf("退出\n");
			break;
		default:
			printf("输入错误,请看选项重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

这是之前我们写的(简洁版,只有框架,没有内容)

这里的1,2,3,4,0的数字是因为我们之前在menu里说明这些数字代表什么,所以才知道它们分别代表着加法减法等等

为了使得数据的可读性更清晰,我们便可以用枚举

//枚举应用的例子
//计算器(加减乘除)

enum jisuanqi
{
	exit,//0
	add,//1
	sub,//2
	mul,//3
	div//4
};
void menu()
{
	printf("**请输入选择**\n");
	printf("**  1. add  **\n");
	printf("**  2. sub  **\n");
	printf("**  3. mul  **\n");
	printf("**  4. div  **\n");
	printf("**  0. exit **\n");
}
int main()
{
	int input = 0;
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case add:
			break;
		case sub:
			break;
		case mul:
			break;
		case div:
			break;
		case exit:
			printf("退出\n");
			break;
		default:
			printf("输入错误,请看选项重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

加上了枚举,每个case代表什么我们也就一目了然了,也不需要看menu来查找每个数字的含义

2.联合体

2.1联合体的声明

和结构体相似,联合体也是一个或者多个成员构成,这些成员也可以是不同的类型

但是编译器只为联合体的最大的成员分配足够大的内存空间。联合体的特点是所有成员共有同一个内存空间,所以也叫做共用体

给联合体其中一个成员赋值,其他成员的值也跟着变化

//联合体的声明
union S
{
	char a;
	int n;
};

2.2联合体的特点

联合体的成员是共用同一块内存空间。所以一个联合变量的大小,至少是最大成员的大小

上图可知变量的大小是最大变量类型int的大小,成员的内存空间是同一个位置

2.3对比结构体和联合体

struct S
{
	char c;
	int i;
};
struct S s = { 0 };

union Un
{
	char c;
	int i;
};
union Un un = { 0 };

从上图我们也能明显看出两者之间的差异

2.4联合体内存大小的计算

联合体的大小至少是最大成员的大小

当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍

例如:

union S
{
	char arr[6];
	int i;
};

int main()
{
	union S s = { 0 };
	printf("%zd\n", sizeof(s));
	return 0;
}

试着运算一下结构体S的内存空间

下列是运算结果:

发现并不是我们本来想的6

原因是char arr[6]相当于六个char类型的变量,所以数组内存是6,但是对齐数是1,而int i的对齐数是4,发现6并不是4(最大对齐数)的整数倍,所以结构体内存就扩大到了8

由此看出,联合体虽然可以节省空间,但不是绝对的节省

联合体的应用:

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;
};

上述代码是关于礼品券的信息构成的结构体,其中

int stock_number;//库存量          double price; //定价          int item_type;//商品类型

这三种是公用的

其余的结构体里联合体中新的三个小结构体则是三种不同礼品特有的属性

因为这三组属性只在特殊的礼品中才会用到,所以不会同时出现,这就可以使用联合体

而在结构体中创建新的小联合体,以及小联合体中再创建三个小小结构体都是匿名创建

匿名创建是因为再item的变量结构体中,我们们每使用一次,这些结构体和联合体也就使用一次,也只适用于item中,所以可以使用匿名创建。

2.5联合体的应用练习

关于之前判断电脑是大小端字节序存储的代码就可以使用联合体

union U
{
	int i;
	char c;
};
int main()
{
	union U u = { 0 };
	u.i = 1;
	if (u.c == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	return 0;
}

相关文章:

  • OpnenHarmony 开源鸿蒙北向开发——1.开发环境搭建(DevEco Studio 5.03)
  • 高主频GPU+RTX4090:AI生图性能优化超150%
  • GIT标签(Tag)操作
  • Cursor与Coze结合开发电影推荐系统:一次高效的技术实践
  • 数据结构——串、数组和广义表
  • golang开发支持onlyoffice的token功能
  • 自定义uniapp组件,以picker组件为例
  • SpringBoot第三站:配置嵌入式服务器使用外置的Servlet容器
  • SQL注入第7关
  • DNS主从服务器
  • 【第K小数——可持久化权值线段树】
  • IIS 服务器日志和性能监控
  • 蓝桥杯嵌入式赛道复习笔记2(按键控制LED灯,双击按键,单击按键,长按按键)
  • element-plus中Popconfirm气泡确认框组件的使用
  • 基于 Docker 和 Flask 构建高并发微服务架构
  • UnitTest框架管理测试用例——python自动化测试
  • Golang学习笔记_49——解释器模式
  • mysql-查看binlog日志
  • 基于SpringBoot+Vue的幼儿园管理系统+LW示例参考
  • GPU视频编解码:Jetson VPI+multimedia_api视频编解码入门(一)
  • 范宇任上海宝山区副区长
  • 聚焦各领域顶尖工匠,《上海工匠》第十季于五一播出
  • 一季度我国服务进出口总额19741.8亿元,同比增长8.7%
  • 连演三场,歌剧《义勇军进行曲》在上海西岸大剧院上演
  • 全过程人民民主研究基地揭牌,为推动我国民主政治建设贡献上海智慧
  • 热点问答|第三轮间接谈判结束,美伊分歧还有多大?