【C/C++】自定义类型 枚举&联合

学习导航

写在前面

枚举

枚举类型的定义

枚举的使用

枚举的大小计算

枚举的优点

联合(共用体)

联合类型的定义

联合的内存分配

联合大小的计算


写在前面


我们知道的C语言中的自定义类型有:

结构   位段   枚举   联合

其中结构和位段在前两篇文章中已经学习过,传送门奉上:

【C/C++】结构体&内存对齐icon-default.png?t=M85Bhttp://t.csdn.cn/5nbNG【C/C++】你知道位段吗?段位?不,是位段!icon-default.png?t=M85Bhttp://t.csdn.cn/LjnAj接下来,我们一起学习剩余两种自定义类型。


枚举


枚举顾名思义就是一一列举。
把可能的取值一一列举。
比如我们现实生活中:
一周的星期一到星期日是有限的7天,可以一一列举。
性别有:男、女、保密,也可以一一列举。
月份有12个月,也可以一一列举

枚举类型的定义

enum Day//星期
{
    //枚举的可能取值
    //枚举的可能取值都是常量,不可修改
	Mon,    //注意是逗号
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun     //结尾并没有;
};
enum Sex//性别
{
	MALE,
	FEMALE,
	SECRET
};
enum Color//颜色
{
	RED,
	GREEN,
	BLUE
};
以上定义的 enum Day enum Sex enum Color 都是 枚举类型
{} 中的内容是枚举类型的可能取值,也叫 枚举常量 (常量不可修改但是可以赋初值) 
这些可能取值都是有值的,默认从 0 开始,一次递增 1。
当然在定义的时候也可以赋初值。
例如:
 
enum Color//颜色
{
	RED = 1,
	GREEN = 2,
	BLUE = 4
};

或者

enum Color//颜色
{
	RED = 1,
	GREEN,//2
	BLUE  //3
};

某个值复制后,后面的值如果没有赋值默认增加1。

枚举的使用

定义一个枚举类型的变量:

#include
enum Color//颜色
{
	RED,
	GREEN,
	BLUE 
};
int main()
{
	enum Color col = RED;
	
    printf("%d", col);   //打印RED的值为0
	
	return 0;
}

既然RED的值为0,那我们能否将0赋值给col呢?

	enum Color col = 0;//这样是否可行呢?

运行之后,我的编译器编译成功而且顺利运行。

但是并不代表这个语法在所有编译器下都是正确的。这取决与编译器对语法的容忍程度。

所以,只能拿枚举常量给枚举变量赋值,才不会出现类型的差异

枚举的大小计算

之前计算结构体的大小时,结构体的成员都有明确的类型,结合内存对齐的知识就可以得到

结构体的大小。而我们发现枚举里的成员都是常量没有类型,甚至貌似都没有一条完整的语

句,那该如何计算呢?

我们不妨先用sizeof求出它的大小:

	printf("%d", sizeof(enum Color));  

运行之后,其结果是4。

解释:

回顾之前介绍枚举类型,枚举{}里面所列的是枚举的可能取值。

例如定义该枚举类型的变量:

enum Color col = BLUE;

col只能是{}中枚举的可能取值中的任意一个

而之所以结果是4,是因为在我所使用的编译器下常量大小为4字节

到这里,我们可能会好奇,这个玩意有什么用啊?

我们用#define不也能定义常量吗?

#define RED 0
#define GREEN 1
#define BLUE 2

那我们就谈一谈枚举的优点。

枚举的优点

我们可以使用 #define 定义常量,为什么非要使用枚举?
枚举的优点:
1. 增加代码的可读性和可维护性
2. #define 定义的标识符相比较,枚举有类型检查,更加严谨。
3. 防止了命名污染(封装)
4. 便于调试
5. 使用方便,一次可以定义多个常量
此外,今后我们利用枚举来设置程序的菜单会显得更加美观。

联合(共用体)

联合与结构非常的相似,主要区别就在于联合这两个字。

联合的特征:联合体所包含的成员变量使用的是同一块空间

联合类型的定义

 直接看代码:

//联合类型的声明
union Un
{
	char c;
	int i;
};
//联合变量的定义
union Un un;

这与结构体很相像,但是当我们计算一下它的大小时:

	printf("%d\n", sizeof(union Un));

结果是 4

如果它是结构体的话,那么结果应该是 8

那我们就一起分析一下联合体的内存分配,看看差异从何而来。

联合的内存分配

有这样一个联合体类型:

union Un
{
	char c;
	int i;
	double  n;
};

union Un un;//定义变量

我们采用暴力的方法,直接打印un每个成员的地址看看:

int main()
{
	union Un un;
	printf("%p\n", &un);
	printf("%p\n", &un.c);
	printf("%p\n", &un.i);
	printf("%p\n", &un.n);
	return 0;
}

运行之后:

【C/C++】自定义类型 枚举&联合_第1张图片

它们的起始地址都相同,也就说明他们所用的其实就是同一块空间 。

【C/C++】自定义类型 枚举&联合_第2张图片

这也就意味着,我们要改变任何一个成员变量的值,都会改变另外两个成员变量的值

例如:

现在un的i中存入0x11223344

int main()
{
	union Un un;
	un.i = 0x11223344;
	return 0;
}

【C/C++】自定义类型 枚举&联合_第3张图片

然后改变un的c的值,看看内存如何变化:

	un.c = 0x55;

【C/C++】自定义类型 枚举&联合_第4张图片

果然如我们所想。

联合大小的计算

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

结果如下:

本章完! 

你可能感兴趣的:(c进阶系列,c++,c语言)