自定义类型之枚举和联合

该文章将详细介绍除结构体外的另外两种自定义类型--------枚举类型与联合类型。

1.枚举

枚举顾名思义就是------一一列举。
把所有可能的取值一一列举出来。
比如我们现实生活中:

星期一到星期天可以一一列举。
性别男女可以一一列举
月份12个月可以一一列举

这里就可以使用枚举了

1.1枚举类型的定义

enum Day//星期
{
	Mon,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};
enum Sex//性别
{
	MALE,
	FEMALE
};
enum Color//颜色
{
	RED,
	GREEN,
	BLUE
};

以上的 enum Day ,enum Sex,enum Color,都是枚举类型,它们是属于类型的,跟int ,char ,short,,等等是一样,只不过是自己定义的。{ }里面的是枚举类型的可能取值,叫做枚举常量
注意这些不是成员,是枚举类型的可能取值。
这些取值是都有值的,默认是从0开始,依次往下递增1,当然也可以在定义的时候给它进行初始化赋值。还有赋值后它就不能再改变了,因为它是‘ 常量 ’。

在这里插入图片描述
也可以在定义的时候初始化赋值。

enum Color//颜色
{
	RED=5,
	GREEN=8,
	BLUE=4
};

1.2枚举的优点

为什么要使用枚举?
我们可以用#define 定义常量,为什么要用枚举?
枚举的优点:

1. 增加代码的可读性和可维护性
2. 和#define 定义的标识比较枚举定义的标识,枚举有类型检查,更加严谨
3. 防止了命名污染(封装)
4. 可以调试观察,便于调试
5. 使用方便,一次可以定义多个常量

1.3枚举的使用

enum Color//颜色
{
	RED=5,
	GREEN=8,
	BLUE=4
};
int main()
{
	enum Color col = BLUE;//枚举变量col只能由枚举常量赋值,才不会出现类型差异
	//如果这样写: RED=3;可以吗?
	return 0;
}

2.联合(共用体)

2.1联合类型的定义

联合也是一种特殊的自定义类型
这种类型定义的变量也包含一系列的成员,特点是这些成员公用同一块空间(所有联合也叫共用体)
比如:

//联合类型的声明
union UN
{
	char c;
	int i;
};
//联合类型的定义
union UN un;
//联合成员的访问    (un.c)   (un.i)
//计算联合类型变量的大小
printf("%d\n", sizeof(un));

2.2联合的特点

1.联合的成员是共用同一块内存空间的,这样的一个联合变量的大小,至少是最大成员的大小(因为联合至少要有能力保存最大的成员)
2.联合的成员之间不能同时使用,使用其中一个,其他都不能使用。

union UN
{
	char c;//1字节
	int i;//4字节
};
union UN un;
int main()
{
	printf("%p\n", &un);
	printf("%p\n", &(un.c));
	printf("%p\n", &(un.i));
	return 0;
}
//上面输出结果相同吗?为什么呢?

在这里插入图片描述
说明char c,与int i,共用同一个地址,int i 4个字节中,c占用了一个1字节。
在这里插入图片描述

union Un
{
 int i;
 char c;
};
union Un un;
//下面输出的结果是什么?
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);

在这里插入图片描述
i,和c同时都使用了,都给各自赋值后,原来自己的值就会发现变化,因为它们共用同一块空间
在这里插入图片描述

2.3联合大小的计算

  • 联合的大小至少是最大成员的大小
  • 当最大成员大小不是最大对齐数的整数倍时候,就要对齐到最大对齐的整数倍。
    例如:
union Un1
{
	char c[5];
	int i;
}un1;
union Un2
{
	short c[7];
	int i;
}un2;
int main()
{
	//下面输出大小是多少?
	printf("%d\n", sizeof(un1));
	printf("%d\n", sizeof(un2));
	return 0;
}

结果:
在这里插入图片描述
解析:

union Un1
{
	char c[5];//这里大小至少是最大成员5,但最大对齐是4,而5不是4的倍数,所有答案只能是8
	int i;
}un1;
union Un2
{
	short c[7];//这里大小至少是最大成员14,而最大对齐数是4,而14不是4的倍数,所有答案只能是16了
	int i;
}un2;

还有一个与之相关的知识:利用联合的知识怎么证明当前机器是大段存储还是小段存储?
解1:

int check()//利用char类型指针解引用访问1个字节,如果数据在内存中倒着存,那访问1字节就能访问到1
{
	int i = 1;
	int* p = &i;
	return *((char*)p);
}
int main()
{
	int ret=check();
	if (ret == 1)
	{
		printf("小段\n");
	}
	else
		printf("大段\n");
	return 0;
}

解2:

int check()
{
	union Un
	{
		char c;
		int i;
	}un;
	un.i = 1;
	return un.c;//利用联合共用相同空间,给i赋值1,那c也存着i的数据,如果小段,那么c就是1

}
int main()
{
	int ret=check();
	if (ret == 1)
	{
		printf("小段\n");
	}
	else
		printf("大段\n");
	return 0;
}

结果:
在这里插入图片描述

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小陶来咯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值