自定义类型:枚举(enum)+联合体(union)

枚举+联合体

一.枚举

1.枚举类型的声明

  • 枚举顾名思义就是一一列举,把可能的取值一一列举。

比如我们现实生活中:

  1. 一周的星期⼀到星期日是有限的7天,可以一一列举。
  2. 性别有:男、女、保密,也可以一一列举。
  3. 月份有12个月,也可以一一列举。
  4. 三原色,也是可以一一列举。

这些数据的表示就可以使用枚举了,代码如下:

c 复制代码
#include<stdio.h>
enum Day//星期 
{
	//该枚举类型有七种可能值,它们都是常量,被称为枚举常量
	Mon,
	Tues,
	Wed,
	Thur=9,
	Fri,
	Sat,
	Sun
};
int main()
{
	enum Day day1 = Mon;
	enum Day day2 = Sun;
	enum Day day3 = 7;//error,不能为枚举类型的变量(day3)赋值,只能赋值为枚举常量(Sun)

	printf("%d\n", Mon);//0
	printf("%d\n", Tues);//1
	printf("%d\n", Wed);//2
	printf("%d\n", Thur);//9
	printf("%d\n", Fri);//10
	printf("%d\n", Sat);//11
	printf("%d\n", Sun);//12
	return 0;
}
  1. 以上定义的 enum Day ,是枚举类型。
  2. { }中的内容是枚举类型的可能取值,也叫枚举常量。
  3. 枚举类型的值通常是整数常量。
  4. 这些可能取值都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值,后面的值也是依次递增1。

2.枚举类型的优点

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

枚举的优点:

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

  2. 和 #define 定义的标识符比较枚举有类型检查,更加严谨。

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

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

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

3.枚举类型的使用

  • 枚举举例:写一个计算器完成整数的加法,减法,乘法,除法
c 复制代码
#include<stdio.h>
enum Option
{
	EXIT,//0
	ADD,//1
	SUB,//2
	MUL,//3
	DIV//4
};
void menu()
{
	printf("*************************\n");
	printf("**1:add           2:sub**\n");
	printf("**3:mul           4:div**\n");
	printf("**0:exit                 \n");
	printf("*************************\n");
}
int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}
int Cal(int(*pf)(int, int))
{
	int ret = 0;
	int x = 0;
	int y = 0;
	printf("请输入两个数:>");
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("%d\n", ret);
}
int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			Cal(Add);
			break;
		case SUB:
			Cal(Sub);
			break;
		case MUL:
			Cal(Mul);
			break;
		case DIV:
			Cal(Div);
			break;
		case EXIT:
			printf("退出\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

二.联合体

1.联合体类型的声明

  1. 像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型,但是编译器只为最大的成员分配足够的内存空间。
  2. 联合体的特点是所有成员共⽤同⼀块内存空间。所以联合体也叫:共用体
c 复制代码
#include<stdio.h>
union Un//联合体
{
	char c;
	int i;
};
int main()
{
	printf("%zd\n", sizeof(union Un));//4个字节
	return 0;
}
  • 运行可知联合体union Un只占用4个字节,这是为什么呢?

2.联合体的特点

  1. 联合的成员是共用同一块内存空间的,这样一个联合变量的大小至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。
  2. 修改联合体其中⼀个成员,其他成员的值也跟着变化。
c 复制代码
#include<stdio.h>
union Un
{
	char c;
	int i;
};
int main()
{
	union Un un = { 0 };
	printf("& un   =%p\n", &un);
	printf("&(un.c)=%p\n", &(un.c));
	printf("&(un.i)=%p\n", &(un.i));
	return 0;
}
c 复制代码
#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);//11223355
	return 0;
}

3.相同成员的结构体和联合体对比

c 复制代码
#include<stdio.h>
struct S//结构体
{
	char c;
	int i;
};
union Un//联合体
{
	char c;
	int i;
};
int main()
{
	printf("%zd\n", sizeof(struct S));//8个字节
	printf("%zd\n", sizeof(union Un));//4个字节
	return 0;
}
  • 对比一下相同成员的结构体和联合体的内存布局情况。

4.联合体大小的计算

  1. 联合的大小至少是最大成员的大小。
  2. 当最大成员大小不是最大对齐数的整数倍的时候,联合的大小就是最大对齐数的整数倍。
c 复制代码
#include<stdio.h>
union Un
{
	char arr[5];
	//相当于五个char变量,char c1;char c2;char c3;char c4;char c5;
	//自身大小:1,默认对齐数:8,对齐数:1

	int i;//自身大小:4,默认对齐数:8,对齐数:4

	//二者的最大对齐数是4,联合体的总大小是4的倍数,
	//而5不是4的倍数,所以联合体的大小是8
};
union Un2
{
	short c[7];//14  2 8 2
	int i;//         4 8 4
};
int main()
{
	printf("%zd\n", sizeof(union Un));//8
	printf("%d\n", sizeof(union Un2));//16
	return 0;
}

5.联合体的练习(判断大小端)

c 复制代码
#include<stdio.h>
int check_sys()
{
	union
	{
		int i;
		char c;
	}un;
	un.i = 1;
	return un.c;//返回1是小端,返回0是大端 
}
int main()
{
	if (check_sys() == 1)
		printf("小端\n");
	else
		printf("大端\n");
	return 0;
}

6.联合体节省空间例题

  • 比如,我们要搞一个活动,要上线一个礼品兑换单,礼品兑换单中有三种商品:图书、杯子、衬衫。每⼀种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。
  1. 图书:书名、作者、页数。
  2. 杯子:设计。
  3. 衬衫:设计、可选颜色、可选尺寸。

那我们不耐心思考,直接写出以下结构:

c 复制代码
#include<stdio.h>
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;//尺寸
};
  • 上述的结构其实设计的很简单,用起来也方便,但是结构的设计中包含了所有礼品的各种属性,这样使得结构体的大小就会偏大,比较浪费内存。因为对于礼品兑换单中的商品来说,只有部分属性信息是常用的。

比如:

  • 商品是图书,就不需要design、colors、sizes。所以我们就可以把公共属性单独写出来,剩余属于各种商品本身的属性使用联合体起来,这样就可以介绍所需的内存空间,一定程度上节省了内存,代码如下:
c 复制代码
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;
	//g.item.book.num_pages=20;
}g;

创作不易,如果能帮到你的话能赏个三连吗?感谢啦!!!

相关推荐
喵叔哟6 分钟前
重构代码中引入外部方法和引入本地扩展的区别
java·开发语言·重构
尘浮生12 分钟前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
hopetomorrow26 分钟前
学习路之PHP--使用GROUP BY 发生错误 SELECT list is not in GROUP BY clause .......... 解决
开发语言·学习·php
小牛itbull36 分钟前
ReactPress vs VuePress vs WordPress
开发语言·javascript·reactpress
请叫我欧皇i1 小时前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript
闲暇部落1 小时前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
GIS瞧葩菜1 小时前
局部修改3dtiles子模型的位置。
开发语言·javascript·ecmascript
chnming19871 小时前
STL关联式容器之set
开发语言·c++
带多刺的玫瑰1 小时前
Leecode刷题C语言之统计不是特殊数字的数字数量
java·c语言·算法
爱敲代码的憨仔1 小时前
《线性代数的本质》
线性代数·算法·决策树