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

news2025/1/12 6:10:13

目录

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); // 0
	printf("%d\n",GREEN); //1
	printf("%d\n", BLUE); //2
	return 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 1
	int i;       // 4     4 8 4
};
union Un2
{
	short arr[7]; // 14   2 8 2
	int i;        // 4    4 8 4
};
int main()
{
	//下⾯输出的结果是什么?
	printf("%d\n", sizeof(union Un1)); // 8
	printf("%d\n", sizeof(union Un2)); // 16
	return 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!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2040190.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

打造编程学习的“知识宝库”:高效笔记记录与整理指南

如何高效记录并整理编程学习笔记&#xff1f; 在编程学习的海洋中&#xff0c;高效的笔记记录和整理方法就像一张珍贵的航海图&#xff0c;能够帮助我们在浩瀚的知识中找到方向。如何建立一个既能快速记录又易于回顾的笔记系统&#xff1f;如何在繁忙的学习中保持笔记的条理性…

MySQL的字符集配置

MySQL的字符集配置 创建database创建表插入数据查看字符集配置查看字符集的比较规则关于字符集的配置修改字符集总结 创建database create database dbtest1; show databases;use dbtest1;创建表 create table employees(id int,name varchar(15));插入数据 insert into empl…

二分查找专题——基础二分查找

一、题目解析 二、算法分析 找到数组的中心值与target比较&#xff0c;如果中心值大于target则证明target有可能在数组的左边&#xff08;还有一种情况是不存在&#xff09;&#xff0c;反之在数组的右边。重新设置左右边界&#xff0c;折半数组的长度&#xff0c;如此反复&am…

50kg双电多旋翼大载重无人机技术详解

随着无人机技术的飞速发展&#xff0c;大载重无人机因其在物流运输、应急救援、农业植保、环境监测等领域的广泛应用而备受关注。本文将深入解析一款设计承载量达到50kg级别的双电多旋翼大载重无人机&#xff0c;从机体结构设计、动力系统、飞行控制系统、载重挂载系统、能源管…

docker 部署 遇到的一些问题

1. nacos 部署问题 1.1 问题 springboot 服务器启动失败 AnnotationNacosPropertySourceBuilder - There is no content for NacosPropertySource from dataId[rsa.yaml] , groupId[DEFAULT_GROUP] , properties[{accessKey${nacos.access-key:}, clusterName${nacos.cluster…

宝塔面板如何修改域名和网站名

目录 前言修改域名修改网站名 前言 BT宝塔面板是一款安全高效的服务器运维平台&#xff0c;windows和Linux系统都可以使用&#xff0c;安装也简单&#xff0c;相信很多开发者都在用它。 但当我们创建的网站需要更换新的域名&#xff0c;面板中的网站名官方却没有给修改的地方&…

sql语句优化(mysql select语句)-索引方式

1、上图是mysql user表的一小部分数据,一共有: 100万条数据 2、假如现在需要查询name列的某一条数据&#xff08;name‘user3’&#xff09; 3、下图是查询优化器评估的最佳方案&#xff0c;索引我删除了还走索引&#xff0c;还他呀的在&#xff0c;奇怪&#xff0c;就先不研究…

89. UE5 RPG 实现伤害 冷却 消耗技能描述

在上一篇文章里&#xff0c;我们能够通过富文本显示多种格式的文字&#xff0c;并显示技能描述。在这一篇文章里&#xff0c;我们继续优化技能描述&#xff0c;将技能说需要显示的内容显示出来。 实现火球术的基础描述 首先&#xff0c;我们现实现火球术的基础描述&#xff0…

kettle将Excel数据导入oracle

Excel数据导入Oracle示例 Kettle将Excel数据导入Oracle过程记录如下&#xff1a; 3、编辑转换 &#xff08;1&#xff09;Excel输入控件 双击Excel输入&#xff0c;重命名控件名称get_data&#xff0c;在文件选项卡浏览选择Excel文件&#xff08;若不能识别Excel文件&#…

关系,条件和逻辑操作符详解

1关系操作符 C 语言用于比较的表达式&#xff0c;称为 “关系表达式”&#xff08;relational expression&#xff09;&#xff0c;里面使用的运算符就称 为“关系运算符”&#xff08;relational operator&#xff09;&#xff0c;主要有下面6个。 • > 大于运算符 • &…

C++之模版初阶

目录 前言 1.泛型编程 2.函数模版 2.1函数模版概念 2.2函数模版格式 2.3函数模版的原理 2.4函数模版的实例化 2.5模版参数的匹配原则 3.类模版 3.1类模版的定义格式 3.2类模版的实例化 结束语 前言 前面我们学习了C的类与对象和内存管理&#xff0c;接下来我们继续学习…

docker资源控制与数据卷

docker数据卷 容器和宿主机之间数据共享---------挂载卷------------容器内的目录和宿主机的目录进行挂载。实现数据文件共享。 容器的生命周期有限&#xff0c;一旦重启所有对容器内部文件数据修改以及保存的数据都会被初始化&#xff0c;为了防止数据的丢失&#xff0c;重要…

uni-app发布安卓app打包时必须在APP模块配置中选中需要的模块

最近尝试开发一个语音对话的app&#xff0c;在调试阶段没有选中“record录音”模块&#xff0c;安卓基座运行在雷电模拟器上是没有问题的&#xff0c;但是直接云打包在手机上运行就不行了&#xff0c;语音输入没有反应。 经过试验发现是manifest.json没有勾选APP模块配置中的“…

在本地电脑部署属于你的AI大模型

前言&#xff1a; 现在的ai很多&#xff0c;让我看得有些眼花缭乱&#xff0c;随着ai的发展&#xff0c;现在已经有很多ai的大模型已经支持开源&#xff0c;所以现在支持部署一个大模型在自己电脑上&#xff0c;数据私人化。 如果不知道自己是否需要或者是否合适配置可以跳到…

Unity(2022.3.38LTS) - 初步学习C#

目录 一. C#简介 二. 配置代码编辑器 三. C#基本语法 四. 创建脚本 创建C#脚本的方式 1. 在文件夹新建 2. 直接在物体组件创建 五. 例子 扩展物体旋转的方式: 一. C#简介 Unity 中使用的 C# 是一种面向对象的编程语言&#xff0c;具有强大的功能和广泛的应用。 特点…

【笔记】MSPM0G3507移植RT-Thread——MSPM0G3507与RT_Thread(二)

一.创建新工程 找到"driverlib\empty"空白工程&#xff0c;CTRLC然后CTRLV复制副本 重命名为G3507_RTT 打开KEIL工程 双击empty.syscfg&#xff0c;然后打开SYSCONFIG 我的不知道为啥没有48pin选项&#xff0c;如果你也一样&#xff0c;可以跟着我做&#xff0c;如果…

WebDeveloper:1靶机

端口扫描 靶机ip地址为192.168.153.158 目录扫描 访问80端口 拼接访问 /ipdata 发现了一个流量包 放在 wireshark 查看&#xff0c;找到 账号密码 账号&#xff1a;webdeveloper 密码&#xff1a;Te5eQg&4sBS!Yr$)wf%(DcAd 拼接 /wp-login.php 找到登录框 登录成功 找…

vue3+Element Plus功能组件封装——顶部导航(动态渲染+样式调整)

网页顶部的导航栏&#xff0c;一般由代码动态生成 菜单数据在文件内统一配置&#xff0c;方便增删改查&#xff0c;导入后可自动生成导航菜单 代码如下 1.dom部分&#xff08;简单示例&#xff09; <el-menu mode"horizontal" :default-active"currentPath…

java Spring|day1.Spring基础

框架 Core IoC容器AOP功能数据绑定类型转换等 TestingData AccessWeb Servlet 核心 IOC容器 定义 IoC&#xff08;Inversion of Control&#xff09;是控制反转的意思&#xff0c;这是一种面向对象编程的设计思想。 优点 在不采用这种思想的情况下&#xff0c;我们需要自…

51单片机-动态数码管显示

动态数码管显示就是在数码管中显示多个数字&#xff0c;利用了人眼的视觉差显示了数字&#xff0c;但是存在一个问题&#xff0c;在顺序执行显示数字和数值的设置时候&#xff0c;数码管的显示数据会出现错乱&#xff0c;因此&#xff0c;需要执行消影&#xff0c;每次在数码管…