自定义类型:联合和枚举

自定义类型:联合和枚举

上文我们了解到了对于C语言中没有定义的类型,我们可以用结构体自己重新定义一个适用的类型。那么自定义类型除了结构体还有另外两种自定义类型,分别是联合、枚举

1.联合体类型的声明

像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以是不同的类型。但是编译器只为最⼤的成员分配⾜够的内存空间。联合体的特点是所有成员共⽤同⼀块内存空间。所以联合体也叫:共⽤体
给联合体其中⼀个成员赋值,其他成员的值也跟着变化。

#include <stdio.h>
//联合类型的声明
union Un
{
 char c;
 int i;
};
int main()
{
 //联合变量的定义
 union Un un = {0};
 //计算联合体变量的⼤⼩
 printf("%d\n", sizeof(un));
 return 0;
}

我们发现计算的结果如下图所示,不难发现联合体的特点是所有成员共⽤同⼀块内存空间,只为联合体中最大的成员分配足够大的空间。

2.联合体的特点

联合的成员是共⽤同⼀块内存空间的,这样⼀个联合变量的⼤⼩,⾄少是最⼤成员的⼤⼩(因为联合⾄少得有能⼒保存最⼤的那个成员)。
我们从下面的代码来讨论联合体的特点吧!

#include <stdio.h>
//联合类型的声明
union Un
{
 char c;
 int i;
};
int main()
{
 //联合变量的定义
 union Un un = {0};
 // 下⾯输出的结果是⼀样的吗?
 printf("%p\n", &(un.i));
 printf("%p\n", &(un.c));
 printf("%p\n", &un);
 return 0;
}

如下图所示,我们发现打印出联合体中成员的地址竟然是一样的,再次证明了联合的成员是共⽤同⼀块内存空间的。

我们来看另一端代码,继续探讨联合体的特点。

#include <stdio.h>
//联合类型的声明
union Un
{
 char c;
 int i;
};
int main()
{
 //联合变量的定义
 union Un un = {0};
 un.i = 0x11223344;
 un.c = 0x55;
 printf("%x\n", un.i);
 return 0;
}

通过代码调试我们发现,联合体中对char c的修改是在int i的第一个字节地址处修改,得出结论:联合的成员是共⽤同⼀块内存空间的。
在这里插入图片描述
在这里插入图片描述
打印结果如下:
在这里插入图片描述

下面我运用图解的方式来理解联合体的特点如下:
在这里插入图片描述

3. 联合体⼤⼩的计算

• 联合的⼤⼩⾄少是最⼤成员的⼤⼩。
• 当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候,就要对⻬到最⼤对⻬数的整数倍。

#include <stdio.h>
union Un1
{
 char c[5];//最大成员大小为5,最大对齐数为4,5不是4的整数倍,所以Un1的大小为8
 int i;
};
union Un2
{
 short c[7];//最大成员大小为2*7=14,最大对齐数为4,14不是4的整数倍,所以Un2的大小为16
 int i;
};
int main()
{
 //下⾯输出的结果是什么?
 printf("%d\n", sizeof(union Un1));//8
 printf("%d\n", sizeof(union Un2));//16
 return 0;
}

打印结果如下图所示:
在这里插入图片描述

我们发现联合体的大小计算结果不是最大成员的大小,因为当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候,就要对⻬到最⼤对⻬数的整数倍。

4.相同结构体和联合体的对比

//结构体
struct S
{
 char c;
 int i;
};
struct S s = {0};
//联合体
union Un
{
 char c;
 int i;
};
union Un un = {0};

上面的结构体和联合体内存对比图解:
在这里插入图片描述
我们发现联合体会比结构体更加节约内存。

5.联合体的运用

使用联合体是可以节省空间的,举例:
比如,学校有多种课程,
理科生:语文,数学,英语,物理,化学,生物
文科生:语文,数学,英语,政治,历史,地理
职高生:语文,数学,英语,计算机,专业课
那么语文,数学,英语是必选的,是公共属性,我们可以放在结构体中,另外的科目,为特殊属性,我们可以将特殊属性用联合体来存储,节省空间。

struct course
{
 //公共属性
 int Chinese;//语文成绩
 int Maths;//数学成绩
 int English;//英语成绩
 //特殊属性
 int Physics;//物理成绩
 int Chemistry;//化学成绩
 int Biology;//生物成绩
 int Politics;//政治成绩
 int History;//历史成绩
 int Geography;//地理成绩
 int Computer;//计算机成绩
 int Professional course;//专业课成绩
};

这样用结构体存储占用内存过多,我们可以用联合体进行改进,如下:

struct course
{
 //公共属性
 int Chinese;//语文成绩
 int Maths;//数学成绩
 int English;//英语成绩
 //特殊属性
 union{
	struct 
	{
	int Physics;//物理成绩
    int Chemistry;//化学成绩
    int Biology;//生物成绩
    };
	struct
	{
	int Politics;//政治成绩
    int History;//历史成绩
    int Geography;//地理成绩
    };
	struct 
	{
	int Computer;//计算机成绩
    int Professional course;//专业课成绩
    };
      }
};

我们把公共属性单独写出来,剩余属于各种课程成绩本⾝的属性使⽤联合体起来,这样就可以减少所需的内存空间,⼀定程度上节省了内存。

6. 枚举类型的声明

枚举顾名思义就是⼀⼀列举。
把可能的取值⼀⼀列举。
⽐如我们现实⽣活中:
⼀周的星期⼀到星期⽇是有限的7天,可以⼀⼀列举
性别有:男、⼥、保密,也可以⼀⼀列举
⽉份有12个⽉,也可以⼀⼀列举
三原⾊,也是可以一 一列举
这些数据的表⽰就可以使⽤枚举了。

 enum Day//
星期
{
 Mon,
 Tues,
 Wed,
 Thur,
 Fri,
 Sat,
 Sun
};
enum Sex//
性别
{
 MALE,
 FEMALE,
 SECRET
};

以上定义的enum Day ,enum Sex 都是枚举类型。
{}中的内容是枚举类型的可能取值,也叫枚举常量。
这些可能取值都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值。

enum Color//
颜⾊
{
 RED=2,
 GREEN=4,
 BLUE=8
};
 

7. 枚举类型的优点

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

  1. 增加代码的可读性和可维护性
  2. 和#define定义的标识符⽐较枚举有类型检查,更加严谨
  3. 便于调试,预处理阶段会删除#define 定义的符号
  4. 使⽤⽅便,⼀次可以定义多个常量
  5. 枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使⽤

8. 枚举类型的使⽤

enum Color//
颜⾊
{
 RED=1,
 GREEN=2,
 BLUE=4
 enum Color clr = GREEN;//使⽤枚举常量给枚举变量赋值
};
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值