欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > C语言【自定义类型——枚举与联合】详细!!

C语言【自定义类型——枚举与联合】详细!!

2024/11/30 20:42:29 来源:https://blog.csdn.net/2401_83871176/article/details/141182374  浏览:    关键词:C语言【自定义类型——枚举与联合】详细!!

目录

1、枚举 

1.0、什么是枚举

1.1、枚举类型的优点

2、联合体(共用体)

2.0、什么是联合体

2.1、联合体的特点

2.2、联合体大小的计算

2.2.0、联合体节省空间例子

2.3、联合小练习


1、枚举 

1.0、什么是枚举

枚举,顾名思义,就是一一列举,比如一周星期一到星期天,月份一一列举,又比如颜色列举等等。

在C语言中,枚举的基本语法如下:

● 定义的enum 枚举名 是枚举类型。

{ }中的内容是枚举类型的可能取值,也叫枚举常量 。

注意,枚举常量是不能被修改的。但是可以在定义里赋初值。 

enum 枚举名 {  枚举成员1,  枚举成员2,  ...  枚举成员N  
};

默认情况下,枚举成员的值从0开始递增,但我们也可以指定某个枚举成员的值,此时后续成员的值会在此基础上递增。

✅在这个例子中,Color是枚举的名称,而RED、GREEN和BLUE是枚举的成员。默认情况下,RED的值为0,GREEN的值为1,BLUE的值为2。

#include<stdio.h>
enum Color {RED , GREEN ,BLUE
};
int main()
{enum Color color1 = RED;enum Color color2 = GREEN;enum Color color3 = BLUE;printf("%d\n", RED); // 0printf("%d\n",GREEN); //1printf("%d\n", BLUE); //2return 0;
}

如果指定某个成员的值,后面成员的值依次递增:

1.1、枚举类型的优点

我们本来可以使用#define 定义常量,为什么非要使用枚举呢?

枚举的优点:

1. 增加代码的可读性和可维护性

比如,比如我要写一个计算器-完成整数的加法、减法、乘法、除法时,可以使用枚举类型来定义ADD、SUB等,而不是使用整数1、2等来表示。这样,当看到ADD时,我们可以立即知道它代表的是加法,而无需去查看整数对应的含义。

2. 和#define定义的标识符比较枚举有类型检查,更加严谨。

使用#define宏定义标识符时,预处理器只是简单地将宏名称替换为其对应的值,由于这种替换是在编译之前进行的,并且没有类型信息,因此编译器无法对使用这些宏的变量进行类型检查。而枚举则不同,枚举是一种类型,它定义了一组命名的整型常量。当尝试将一个非枚举类型的值赋给枚举类型的变量时,编译器会进行类型检查,并可能发出警告或错误。

3. 便于调试,预处理阶段会删除 #define 定义的符号。

4. 使用方便,一次可以定义多个常量。

5. 枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用。

2、联合体(共用体)

2.0、什么是联合体

● 像结构体一样,联合体也是由一个或者多个成员构成,这些成员可以是不同的类型

● 但是编译器只为最大的成员分配足够的内存空间。联合体的特点是所有成员共用同一块内存空间。所以联合体也叫:共用体

● 这意味着,当你给联合体的一个成员赋值时,其他成员的值会被覆盖,因为它们共享同一块内存空间。

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

 运行结果:4

2.1、联合体的特点

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

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

运行结果:输出的三个地址一模一样。可见联合的成员是共用同一块内存空间的

✅也可以通过下面这段代码来调试观察:

#include <stdio.h>
//联合类型的声明
union Un
{char c;int i;
};
int main()
{union Un un = { 0 };un.i = 0x11223344;un.c = 0x55;return 0;
}

内存观察: 

i 的第4个字节的内容修改为55了。un 的内存布局图:

2.2、联合体大小的计算

联合的大小至少是最大成员的大小。注意(是至少,但不一定)

当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。 

✅代码: 

#include <stdio.h>
union Un1
{char arr[5]; // 5     1 8 1int i;       // 4     4 8 4
};
union Un2
{short arr[7]; // 14   2 8 2int i;        // 4    4 8 4
};
int main()
{//下⾯输出的结果是什么?printf("%d\n", sizeof(union Un1)); // 8printf("%d\n", sizeof(union Un2)); // 16return 0;
}

如上面Un1中算出最大对齐数是4 ,但最大成员大小是5,所以要对齐到最大对齐数4 的整数倍,结果是8 。算Un2的大小也是一样的思路。

2.2.0、联合体节省空间例子

使用联合体是可以节省空间的。

比如:

我们要组织一个活动,参与者可以通过积分兑换三种不同的奖励:虚拟游戏皮肤、实体纪念品、和赛事访问权限

每种奖励都有一些共同的属性:库存量、所需的积分、奖励类型,以及每种类型特有的其他信息。

其他信息:

虚拟游戏皮肤:皮肤名称、设计
实体纪念品:尺寸、设计、颜色
赛事访问权限:参赛人数

 ✅结构如下:

struct point_list
{//公共属性int stock_number;//库存量double points; //所需积分int reward_type;//奖励类型//特殊属性char title[20];//皮肤名称char design[30];//设计int sizes;//尺⼨int colors;//颜⾊int num_participant;//参赛人数};

上述的结构设计简单,用起来方便,但是结构的设计中包含了所有奖励的各种属性,这样使得结构体的大小偏大,比较浪费内存。

因为对于积分兑换单中的奖励来说,只有部分属性信息是常用的。

比如: 奖励是实体纪念品时,就不需要num_participant,因为它是赛事访问权限的特有信息。 所以我们就可以把公共属性单独写出来,剩余属于各种奖励本身的属性使用联合体起来,这样就可以介绍所需的内存空间,一定程度上节省了内存。

代码:

struct point_list
{//公共属性int stock_number;//库存量double points; //所需积分int reward_type;//奖励类型union {struct{char title[20];//皮肤名称char design[30];//设计}game_skin;struct{int sizes;//尺⼨int colors;//颜⾊char design[30];//设计}souvenir;struct{int num_participant;//参赛人数}rights;}reward;};

2.3、联合小练习

✅写一个程序,判断当前机器是大端?还是小端?这个练习之前也做过,现在我们运用联合体知识实现。

#include<stdio.h>
union Un
{char c;int i;
};int main()
{union Un un = { 0 };un.i = 1; if (un.c == 1){printf("小端\n");}else{printf("大端\n");}return 0;
}

⛳ 点赞☀收藏 ⭐ 关注!

如有不足欢迎评论区指出!

Respect!!!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com