C语言自定义类型【联合体与枚举】

文章目录

1.联合体

1.1联合体的声明

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

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

c 复制代码
#include<stdio.h>
//联合体的声明
union Un
{
	char c1;
	int i;
	char c2;
};

int main()
{
	//创建一个union Un类型的临时变量
	union Un un = { 0 };
	//计算联合体变量的大小
	printf("union Un 大小为%zd", sizeof(un));
	return 0;
}

为什么是4呢?

我们就来了解联合体的特点吧

1.2联合体的特点

联合的成员是共用同一块内存空间,所以一个联合体变量的大小至少是最大成员的大小(因为联合至少得有能力存放最大的成员)。

c 复制代码
#include<stdio.h>
//联合体的声明
union Un
{
	char c1;
	int i;
};

int main()
{
	//创建一个union Un类型的临时变量
	union Un un = { 0 };
	//查看联合成员的地址
	printf("成员i 的地址为  %p\n", &un.i);
	printf("成员c1的地址为  %p\n", &un.c1);
	printf("联合体un的地址为%p\n", &un.c1);

	return 0;
}

可以看到输出的三个地址一模一样。

c 复制代码
#include<stdio.h>

//联合体的声明
union Un
{
	char c1;
	int i;
};

int main()
{
	//创建一个union Un类型的临时变量
	union Un un = { 0 };
	un.i = 0x11223344;
	un.c1 = 0x55;
	//查看联合体成员的值(16进制)
	printf("成员i的为%x\n", un.i);

	return 0;
}

我们通过调试可以看到,i的第4个字节的内容被修改为了55。


这又证明了,联合体的所有成员是共用同一块空间。

成员相同的结构体和联合体进行比较

c 复制代码
#include<stdio.h>

struct Str
{
	char c1;
	int i1;
};

union Un
{
	char c2;
	int i2;
};

int main()
{
	printf("struct Str的大小为%zd\n", sizeof(struct Str));
	printf("union Un的大小为%3zd", sizeof(union Un));

	return 0;
}

他们的成员大小相同,成员顺序相同,但输出的结果还是不同,也就是说结构体和联合体对待成员的存放是不同的。
结构体每个成员有独立的空间,而联合体是共用一块空间

1.3联合体的大小计算

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

2.如果最大成员的大小不是最大对齐数的整数倍时,空间大小要对齐到最大对齐数的整数倍

看代码:

c 复制代码
union Un1//最大对齐数为4(int)
{
	char ch[5];//大小为5(最大)
	int i;//大小为4
};

union Un2//最大对齐数为4(int)
{
	short sh[5];//大小为10(最大)
	int i;//大小为4
};

union Un3//最大对齐数为8(long long)
{
	int arr[5];//大小为20(最大)
	long long lg;//大小为8
};

int main()
{
	printf("union Un1的大小为%zd\n", sizeof(union Un1));
	printf("union Un2的大小为%zd\n", sizeof(union Un2));
	printf("union Un3的大小为%zd\n", sizeof(union Un3));
	return 0;
}

联合体的使用案例

联合体的使用案例

假如我们要搞⼀个活动,要上线⼀个礼品兑换单

礼品兑换单中有三种商品:图书、杯⼦、衬衫。

每种商品都有:库存,价格,商品类型,我们称之为公共属性

其中每个商品有各自的特殊属性

图书:书名,作者,页数

杯子:设计方案

衬衫:设计方案,颜色,尺寸

解决方法一:

c 复制代码
struct gift_list
{
	//公共属性
	int stock_number;//库存
	double price;//价格
	int item_type;//商品类型

	//特殊属性
	char Title[20];//书名
	char Author[20];//作者
	int Num_page;//页数

	char Design;//设计方案(杯子和衬衫都有设计方案)
	char Colors[10];//颜色
	int Size;//尺寸

};

上面的的代码,很暴力,也很方便,但是结构的设计中包含了所有礼物的属性,这样会使得结构体的大小会偏大,比较浪费空间。而且对于单个商品来说,只有部分属性是我要用的。

比如商品是衬衫的话我要用的就是Design、Colors、Size,而Title、Author、Num_page就是不需要的属性

所有我们可以把公共属性独立写出来,剩余各种商品本身的特殊属性就可以使用联合体。这样就可以在一定程度上节省空间。

c 复制代码
struct Gift_List
{
	//公共属性
	int stock_number;//库存
	double price;//价格
	int item_type;//商品类型

	union MyUnion
	{
		struct
		{
			char Title[20];//书名
			char Author[20];//作者
			int Num_page;//页数
		}book;

		struct 
		{
			char Design;//设计方案(杯子和衬衫都有设计方案)
		}mug;

		struct 
		{
			char Design;//设计方案(杯子和衬衫都有设计方案)
			char Colors[10];//颜色
			int Size;//尺寸
		}shirt;
	}item;
};

2.枚举

2.1枚举类型的声明

顾名思义就是将可能的元素进行一一列举

例如我们生活中的:一周的星期一到星期日、十二个月份、三原色;这些都可以一一列举

附上代码

c 复制代码
enum Colors//
{
	RED,
	BLUE,
	GREEN
};

enum Week_By_Day
{
	Mon,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};

以上定义的 颜色,一周都是枚举类型。

而{}里的内容是枚举类型里的可能取值,这也叫做枚举常量。

这些可能取值都是有值的(创建常量的时候肯定是要赋值的)

枚举常量默认从0开始,依次递增1,当然,在声明枚举类型的时候也可以赋初始值。

c 复制代码
enum Direction
{
	NORTH,//初始值在没有赋值的情况下就是0
		  //后面的值发生改变也不会改变前面的值
	EAST,
	WEST = 5,
	SOUTH
};

int main()
{
	printf("%d\n", NORTH);
	printf("%d\n", EAST);
	printf("%d\n", WEST);
	printf("%d\n", SOUTH);
	return 0;
}

初始值在没有赋值的情况下就是0,后面的值发生改变也不会改变前面的值

2.2枚举类型的优点(为什么使用枚举)

明明我们有#define 来定义常量,为什么要使用枚举?

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

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

3.便于调试,预处理阶段会直接将#define定义的符号替换为原来的符号

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

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

2.3枚举类型的使用

c 复制代码
#include<stdio.h>
enum Colors
{
	RED,//0
	BLUE,//1
	GREEN//2
};
int main()
{
	enum Color clr = GREEN;//使⽤枚举常量给枚举变量赋值
	printf("clr的值为%d", clr);
	return 0;
}

补充:

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

结语

最后感谢您能阅读完此片文章,如果有任何建议或纠正欢迎在评论区留言。如果您认为这篇文章对您有所收获,点一个小小的赞就是我创作的巨大动力,谢谢

相关推荐
释厄6236 分钟前
错误无误公理——错误正确本同源都迭代定律——逆转有价值
android·开发语言·kotlin
2601_9628857217 分钟前
如何用 Python计算 CR能量指标(中间意愿指标)?
开发语言·python
slimer20 分钟前
11.C 语言 printf 打印函数详解:格式说明符、宽度精度与安全输出
linux·c语言
Xudde.24 分钟前
HackMe 靶机渗透测试(Vulnhub Writeup)
笔记·学习·安全·web安全
临床数据科学和人工智能兴趣组1 小时前
在R语言的生态系统中,字符串处理一直是一个重要且复杂的任务
开发语言·正则表达式·r语言·r语言-4.2.1
蜗牛互联网1 小时前
Python调用Gemini Structured Outputs实现工单路由门禁
java·开发语言·人工智能·python
先途检测认证1 小时前
塑料、硅胶、不锈钢材质,欧盟食品接触的测试项目有什么区别?
笔记·材质
SEO_juper1 小时前
给网页做可引用性评分:判断内容够不够让 AI 引用(GEO 工具,附代码)
开发语言·人工智能·爬虫·python·seo·独立站
Wang's Blog1 小时前
Java 项目实战: 交友项目 - 产品定位、功能模块与客户端原型解读
java·开发语言·交友
跨知易知识产权1 小时前
美国发明专利和外观专利保护期限分别是多久,起算时间怎么界定?
笔记