自定义类型(3)枚举与联合

在本篇博客中,会介绍枚举类型与联合的概念及应用

🚩枚举类型

枚举,顾名思义就是列举,我们把一些有共同特点的事物集中起来,并把其取值一一列举。
什么是枚举类型?先来看一个声明

enum days
{
	Mon = 1,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};

在这个声明中 enum days就是一个枚举类型, Mon、Tues、Wed…这些则是枚举常量,在日期这样一个大的集合中,有星期一、星期二、星期三…当我们需要让这些日期有值时,就可以使用枚举,请注意:两个大括号之间的是枚举常量,常量是不可以改变的,我们只可以对其初始化,例如代码中的
Mon = 1,那么如果不初始化呢?那就会从第一个常量开始递增 Mon是0,Tues是1,Wed是2…依次递增,那我们初始化以后呢?比如给了Mon = 1,之后的常量的值该是多少?那就从你给的值开始递增,下面依次是 2 3 4 …

注意
枚举类型的变量只能由枚举常量赋值,不然会报错
枚举类型赋值

📍📍枚举类型的优点

那我们为什么使用枚举类型呢?枚举类型的优点是什么?

1.增加了代码的可读性和维护性
2.和宏定义相比多了类型校验,更加严谨
3.便于调试
4.使用方便一次可以定义多个常量

我们稍微联想一下就可以发现,枚举类型的使用其实和宏定义#define 有异曲同工之妙,同样是赋予一个名称含义,但是与宏定义相比,枚举简洁很多,在对一套有特点的事物给值的时候明显枚举类型更加方便,比满篇飞舞的宏定义更容易阅读。
并且我们在之前的代码中发现只有枚举常量才能给枚举变量赋值,否则会报错,这说明他的类型校验是十分严格的,而我们在宏定义的时候只是进行了替换,管他三七二十一,来了我就用,有时候就会产生问题。
至于为什么说他方便调试,这我们就要说起一个古老的知识:一段代码是怎么变成应用程序的?

在这里插入图片描述
大概的流程就是这样,那么我们在这个过程中,预编译过程会进行宏的替换,也就是说,这个时候编译器会把你宏定义的符号,全都替换成后面的值,例如你#define a 10,那么在预编译的时候,他就会把a 全都替换成10,而你调试时什么时候呢?是链接以后生成可执行程序以后你才能调试,这时候,宏定义已经替换完成了,如果出现了问题,你也不知道是哪里出现的,而枚举不一样,枚举是一个类型,里面有常量,我们还可以用枚举类型定义一个枚举变量,这些都是真正存在的,调试的时候你监视,你看内存,都是看的到的,所以我们说,使用枚举类型方便调试。

🚩联合(共用体)

在自定义类型中还有一种形式上与结构体相似,但是在储存上截然相反的类型,就是联合,先看看联合的声明:

union a
{
	int b;
	char c;
	double d;
};

乍一看与结构体的声明很想,调用也一样,直接通过 . 运算符,那么他和结构体的区别在哪里呢?
我们尝试计算一下这个联合的大小 ,如果按照结构体的思路 内存对齐 4 4 8
加一块是16,可是真的是这样吗?
在这里插入图片描述
可以看到,实际上联合的大小是 8,这是也是联合也称共用体的原因,所有成员变量都使用同一块空间,为了证明,我们可以再看一个运行结果:
在这里插入图片描述
这回我们清晰的看到了,三个成员变量打印的地址相同,这也佐证了我们的观点,我们再画图理解一下
在这里插入图片描述
这样就清晰一些了,可以看到明显的共用关系,但是空间一起用,岂不是牵一发而动全身?修改一个变量三个变量的值都改了,事实也是这样,所以我们在使用联合类型的时候,一次通常只使用其中一个的变量,那这样又有什么用呢?
在之前我们说过,类型的一个作用是内存解释,那么我们在使用联合的时候同样可以利用这一点,联合中有很多类型的变量,我想让这块内存用int表示,那就调用int类型的成员变量,想让他怎么解释,就怎么解释。
这里有一个具体的应用:

📍📍联合测定大小端

既然联合可以按照任意成员变量的类型解释,那我们就利用这一点进行大小端的测序

union a
{
	int b;
	char c;
};
int main()
{
	union a s1;
	s1.c = 1;
	if (s1.c == 1)
		printf("小端");
	else 
		printf("大端");
}

我们给s1空间赋值 1,这时空间用二进制表示就是

00 00 00 01//高位------->低位

如果是小端字节序,那么应该是低地址存低位:

01 00 00 00//低地址----->高地址

那如果是大端字节序,就是低地址存高位:

00 00 00 01//低地址----->高地址

由于char类型的大小只有一个字节,那如果是大端,他读取到的就是00,如果是小端,读取到的是 01也就是1,所以可以用联合判断
在这里插入图片描述
可以看到,我们的机器是小端字节序。

📍📍联合的大小计算

联合大小计算的两个规则:
1.联合的空间是所占空间最多的成员变量的大小
2.如果成员变量不是最大对齐数的整数倍,要扩大成整数倍

我们来举个例子

union a
{
	int b;
	char c;
};
int main()
{
	union a s1;
	printf("%d\n", sizeof(s1));
}

这样一段代码,联合s1的大小是什么?他有两个成员变量,一个是int 一个是char,int最大,所以联合的大小是4。
在这里插入图片描述
再看下面这个例子

union a
{
	char c[7];
	int a;
};
int main()
{
	union a s1;
	printf("%d\n", sizeof(s1));
}

如果按照之前的思路,那就是c占七个字节,a占四个,那么c大,联合的大小是7,但实际上呢?
在这里插入图片描述
他是8个字节,原因是联合中也存在着内存对齐的现象,虽然c的大小是7,但是对齐数是1(数组的对齐数是按照数组元素的大小来计算的),而a是4,7并不是4的整数倍,所以要扩大成8。

🚩小结

那么到这里C语言中自定义类型的知识就梳理完了,下面的博客将会继续带大家了解C语言的知识。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值