C语言枚举与联合(共用体)

Posted 蓝乐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言枚举与联合(共用体)相关的知识,希望对你有一定的参考价值。

枚举

顾名思义就是一一列举,把可能的取值一一列举。比如现实生活中:
一周从星期一到星期日共七天,可以一一列举;
性别有男,女,保密,可以一一列举;
月份有十二个月,也可以一一列举。

枚举类型的定义

enum Day
{
	Mon,
	Tues,
	Wes,
	Thur,
	Fri,
	Sat,
	Sun
};

enum Sex
{
	MALE,
	FEMALE,
	SECRET
};

以上定义的eum Day, eum Sex都是枚举类型,{}中的内容是枚举类型的可能取值,也叫枚举常量(这些常量是不可更改的)。这些可能取值都是有值的,默认从0开始,一次递增1,当然在定义的时候也可以赋初值。例如:

enum Color
{
	RED = 1,
	GREEN = 2,
	BLUE = 4
};

在这里插入图片描述

枚举的优点

为什么使用枚举?

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

  1. 增加代码的可读性和可维护性
  2. 和#define定义的标识符比较枚举有类型检查,更加谨慎
    #define定义的标识符是没有类型的,由于C语言的源代码会经过预编译,编译,链接到可执行程序几个阶段,在预编译阶段#define定义的标识符不会被替换为其所指的内容,则没有类型的说明,因此没有枚举类型更严谨。
  3. 防止了命名污染(封装)
    枚举成员放在{}内,防止了与别的变量名冲突。
  4. 便于调试
    调试是在可执行程序过程发生的,#define定义的标识符已经被替换为其所指的内容,可能不方便找到错误;而枚举变量认为其成员名,便于调试。
  5. 使用方便,一次可以定义多个常量

枚举的使用

在使用switch语句时,可以把case后的整型替换成枚举变量可以时代码更据可读性。例如实现一个简易计算器时,我们将各个选项放在枚举类型中,将会大大方便我们的读写代码:

enum Option
{
	EXIT,
	ADD,
	SUB,
	MUL,
	DIV
};

int main()
{
	int input = 0;
	do
	{
		scanf("%d", &input);
		int a = 0;
		int b = 0;
		int ret = 0;
		switch (input)
		{
		case ADD:
			scanf("%d %d", &a, &b);
			ret = Add(a, b);
			break;
		case SUB:
			scanf("%d %d", &a, &b);
			ret = Sub(a, b);
			break;
		case MUL:
			scanf("%d %d", &a, &b);
			ret = Mul(a, b);
			break;
		case DIV:
			scanf("%d %d", &a, &b);
			ret = Div(a, b);
			break;
		case EXIT:
			break;
		default:
			printf("请重新选择:\\n");
			break;
		}
		printf("结果是%d\\n", ret);
	} while (input);
	return 0;
}

枚举类型的大小

下面这个代码的结果是什么呢?

int main()
{
	printf("%d\\n", sizeof(enum Sex));
	return 0;
}

在这里插入图片描述
枚举常量是整型,因此大小是4,也就是说sizeof(enum Sex)sizeof(int)是相等的,但是两者并不是一回事,二者是完全不同的类型

//枚举的使用可以是:
enum Sex s = MALE;
//但不可以是:
enum Sex s = 1;

这是因为enum Sex 类型与 int 类型是不同的。

联合(共用体)

联合类型的定义

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

//联合类型的声明

union SN
{
	char c;
	int i;
};
int main()
{
	//联合变量的定义
	union SN s;
	//计算联合变量的大小
	printf("%d\\n", sizeof(s));
	return 0;
}

在这里插入图片描述
程序运行发现联合变量s的大小是4个字节,这说明:

联合的特点

联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少的有能力保存那个最大的成员)。

    //下面三个语句的结果相同吗?
	printf("%p\\n", &s);
	printf("%p\\n", &(s.c));
	printf("%p\\n", &(s.i));

在这里插入图片描述
程序运行的结果也验证了联合的特点,也就是说,联合s的内存分布如下:
在这里插入图片描述
那么,利用联合的特点,我们对于之前判断大小端存储模式的方法又多了一种,我们先来回顾一下大小端存储模式,对于int a = 1;若为小端存储模式,则a在内存中应为01 00 00 00,若为大端存储模式,则a在内存中应为00 00 00 01. 因此,我们可以利用联合的特性,去除整型a的第一个字节,判断其是否为1,进而判断当前机器是大端存储模式还是小端存储模式:

int judge_sys()
{
	union UN
	{
		char c;
		int i;
	};
	union UN u;
	u.i = 1;
	return u.c;
}

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

联合大小的计算

  1. 联合的大小至少是其最大成员的大小。
  2. 联合也遵循内存对齐规则。比如:
union SNS
{
	int i;
	char ch[5];
};

int main()
{
	printf("%d\\n", sizeof(union SNS));
	return 0;
}

联合的最大成员大小为4,数组ch相当于5个字符变量,每个大小均为1,该联合的最大对齐数为4,因此联合的大小应为4的整数倍8.
在这里插入图片描述

总结

在这里插入图片描述

以上是关于C语言枚举与联合(共用体)的主要内容,如果未能解决你的问题,请参考以下文章

黑马程序员C语言基础(第八天)复合类型(自定义类型)共用体(联合体)枚举 typedef

C语言—自定义类型

C语言—自定义类型

C语言结构体及其内存对齐枚举联合的介绍

C语言自定义类型重难点总结(结构体位段枚举联合)

C语言-枚举共用体