重生之我在异世界学编程之C语言:枚举联合篇

大家好,这里是小编的博客频道
小编的博客:就爱学编程

很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!!

本文目录

  • 引言
  • 正文
    • 枚举(Enum)
      • 1.枚举的定义和基本使用
      • 2.枚举的优点
      • 3.枚举的使用场景
      • 4.枚举与switch语句
    • 联合(Union)
      • 1.联合的定义和基本使用
      • 2.联合与内存对齐
        • (1)联合体大小
        • (2)联合体内存分配
      • 3.联合的使用场景
      • 4.联合的优点
    • 枚举和联合的高级使用
      • 1.枚举的位字段
      • 2.联合的类型转换
      • 3.枚举和联合的组合使用
      • 4.注意事项
  • 快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

引言

C语言中的枚举(Enum)和联合(Union)是两种强大的数据结构,它们在程序设计中扮演着重要角色。枚举提供了一种定义命名常量的方式,使得代码更加清晰和易于管理。而联合则允许在相同的内存位置存储不同的数据类型,这在需要节省空间或处理不同数据格式时非常有用。那就跟着小编一起来看看吧!!!

在这里插入图片描述


那接下来就让我们开始遨游在知识的海洋!

正文


枚举(Enum)

1.枚举的定义和基本使用

枚举是一种用户定义的类型,它允许程序员为一组整数值定义一个名字。这使得代码更加可读和易于维护。枚举通过enum关键字定义,基本格式如下:

enum 枚举类型名 {枚举常量1,枚举常量2,...
};

如果省略枚举类型名,可以定义一个匿名枚举:

enum {枚举常量1,枚举常量2,...
};

注意:

  • 枚举的每个常量都是整数,它们从0开始自动赋值,除非显式指定。

这可以用一个题目体会一下:

判断下列代码运行的结果

#include<stdio.h>
int main() {enum ENUM_A{X1,Y1,Z1 = 255,A1,B1,};enum ENUM_A enumA = Y1;enum ENUM_A enumB = B1;printf("%d %d\n", enumA, enumB);return 0;
}

宝子们可以根据注意猜一下运行结果。






好,跟着小编一起看看这个代码的运行结果:

在这里插入图片描述
为什么是这个结果?

原因: 枚举默认从0开始,所以X1是0,故Y1是1,给了数字后会根据数字向后推,那么Z1是255,A1是256,所以B1是257。

所以我们可以知道:

  • 枚举的每个常量都是整数,它们从0开始自动赋值,若前一个枚举常量被显式指定,后面的枚举常量依次递增1

其实我们在之前的学习已经知道:#define也可以用来定义一个常量,那C语言为什么又要创建枚举类型的语法呢?
存在即合理!枚举有着自己的独一无二的优势,这是#define无法比拟的,那就让我们一起来看看吧!!!

2.枚举的优点

  • (1)提高代码可读性:使用枚举可以代替硬编码的数字,使代码更易读。

我们每个优点都用一个例子来佐证一下:

enum TrafficLight {RED, YELLOW, GREEN
};void controlLight(enum TrafficLight light) {if (light == RED) {printf("Stop at the red light.\n");} else if (light == YELLOW) {printf("Prepare to stop at the yellow light.\n");} else if (light == GREEN) {printf("Go at the green light.\n");}
}
  • (2)类型安全:枚举提供了一种类型安全的方式,防止将错误的值赋给变量。
enum TrafficLight {RED, YELLOW, GREEN
};void controlLight(enum TrafficLight light) {if (light == RED) {printf("Stop at the red light.\n");} else if (light == YELLOW) {printf("Prepare to stop at the yellow light.\n");} else if (light == GREEN) {printf("Go at the green light.\n");}
}
  • (3)便于维护:如果需要更改枚举常量的值,只需在定义处更改,而不需要搜索整个代码库。
enum Status {SUCCESS = 0,FAILURE = 1,ERROR = 2
};// 假设我们需要将SUCCESS的值改为1
enum Status {SUCCESS = 1,FAILURE = 2,ERROR = 3
};

学习了以上内容,那我们再来看看枚举具体使用在哪些场景。

3.枚举的使用场景

枚举常用于表示有限的、命名的常量集合,例如:

  • 状态码(如:打开、关闭)

  • 方向(如:北、南、东、西)

  • 优先级(如:低、中、高)


事实上,除了以上枚举的用法,枚举还可以与swtich语句结合使用,一起来看看吧!!!

4.枚举与switch语句

  • 枚举常与switch语句结合使用,处理基于不同枚举值的条件分支,提高代码的可读性和可维护性。

以下列代码为例感知:

enum Day {Sunday,Monday,// ...
};void printDay(enum Day day) {switch (day) {case Sunday:printf("Sunday");break;case Monday:printf("Monday");break;// ...}
}

简单对枚举的定义与使用,进行了解后,我们再来看看联合这一节的知识。

联合(Union)

1.联合的定义和基本使用

联合是一种特殊的数据类型,允许在同一内存位置存储不同的数据类型。联合通过union关键字定义,基本格式如下:

union 联合类型名 {类型1 成员1;类型2 成员2;...
};

如果省略联合类型名,可以定义一个匿名联合:

union {类型1 成员1;类型2 成员2;...
};

注意:

  • 联合的大小等于其最大成员的大小,且所有成员共享同一块内存空间。

这同样也可以用一个题目来体会一下:

判断下面代码的运行结果

#include <stdio.h>
union Un
{short s[7];int n;
};
int main()
{printf("%d\n", sizeof(union Un));return 0;
}

宝子们同样可以根据注意猜一下运行结果。






好,跟着小编一起看看这个代码的运行结果:

在这里插入图片描述

小编猜想很多宝子们会猜答案是14,实际的结果却是16,这似乎与我们上面说的注意相违背。

但实际上,是不违背的,因为小编还有一个知识点没有和宝子们介绍:

  • 实际上,联合作为一种自定义类型,它在内存中的存储也是存在对齐的。

那我们接下来就走进**联合与内存对齐**这一章的知识。

2.联合与内存对齐

联合的内存对齐取决于最大成员的对齐要求。编译器可能会对联合进行内存对齐,以提高访问效率。


内存对齐是指在创建数据结构时,按照某些规则(通常是硬件平台的要求)将数据成员存放在内存中,以提高访问效率和避免访问异常。对于联合(union)来说,内存对齐同样重要,以下是联合内存对齐规则:

数据成员对齐规则:

  • 结构体或联合的数据成员,第一个数据成员存放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小的整数倍开始。

  • 结构体作为成员:如果一个结构体里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储

  • 结构体的总大小:即sizeof的结果,必须是其内部最大成员长度的整数倍,不足的要补齐。


(1)联合体大小

联合体的大小取决于他所有成员中占用空间最大的一个成员的大小。当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数类型的整数倍。


(2)联合体内存分配

联合体变量的各个成员都是从低字节开始公用的。即:所有的成员都是从低字节开始的。

举例说明

示例1:考虑一个联合体,包含一个char数组、一个int和一个float

union Example {char a[6];int b;float c;
};

分析:
char a[6]占据6个字节。

int b通常占据4个字节。

float c通常占据4个字节。

根据联合体大小的规则,联合体的大小取决于最大成员的大小,即char a[6]的6个字节。但由于6不是4的整数倍,根据内存对齐规则,联合体的大小需要被调整为8个字节,以满足最大对齐数(通常是4或8,取决于平台)。

示例2:内嵌联合体的情况。

union InnerUnion {char a[6];int b;
};struct OuterStruct {short a;union InnerUnion uu1;
};

分析:

short a占据2个字节。

union InnerUnion uu1根据之前的解释,占据8个字节。

因此,struct OuterStruct的总大小需要是其内部最大成员长度的整数倍。在这个例子中,最大成员是union InnerUnion uu1,占据8个字节。所以,struct OuterStruct的总大小为12个字节,以满足内存对齐的要求。

通过这些规则和例子,我们可以看到:

  • 联合的内存对齐是为了确保数据在内存中的存储位置符合处理器的访问要求,同时提高内存访问效率和程序性能。

3.联合的使用场景

联合常用于需要存储多种数据类型但在同一时间只能使用其中一种的场景,例如:

  • 变量的多种表示形式(如:整数或浮点数)

  • 内存管理(如:不同数据类型的缓冲区)


4.联合的优点

  • 节省内存:由于所有成员共享内存,联合可以节省存储空间。
union Data {int integer;float floating;
};int main() {union Data data;data.integer = 10; // 使用整数存储// 此时,内存中存储的是整数10data.floating = 3.14f; // 覆盖内存,现在存储浮点数3.14// 此时,内存中存储的是浮点数3.14
}
  • 提高效率:联合允许在不同数据类型之间进行高效的转换。
union IntFloat {int asInt;float asFloat;
};int main() {union IntFloat value;value.asInt = 0x40490FDB; // 以整数形式存储printf("As float: %f\n", value.asFloat); // 以浮点数形式读取
}

最后,我们再来看看枚举和联合的高级使用

枚举和联合的高级使用

1.枚举的位字段

枚举可以与位字段结合使用,以存储多个标志位。这种方法在需要节省内存时非常有用。

typedef enum {FLAG_A = 1 << 0,FLAG_B = 1 << 1,FLAG_C = 1 << 2
} Flags;struct MyStruct {unsigned int flags : 3;
};int main() {struct MyStruct myStruct;myStruct.flags = FLAG_A | FLAG_C; // 设置标志A和Cif (myStruct.flags & FLAG_A) {printf("FLAG_A is set.\n");}if (myStruct.flags & FLAG_B) {printf("FLAG_B is set.\n");}if (myStruct.flags & FLAG_C) {printf("FLAG_C is set.\n");}return 0;
}

2.联合的类型转换

联合可以用作不同数据类型之间的转换工具。特别是,当需要将相同内存中的数据以不同格式进行解释时,联合可以提供一种有效的方法。


typedef union {float f;uint32_t i;
} FloatIntUnion;int main() {FloatIntUnion data;data.f = 3.14159; // 设置浮点数// 打印浮点数及其对应的整数位模式printf("Float value: %.5f\n", data.f);printf("Integer value: 0x%08X\n", data.i);return 0;
}

3.枚举和联合的组合使用

枚举和联合可以组合使用,以创建复杂的数据结构,这些结构可以根据需要存储不同的数据类型。

typedef enum {INT_TYPE,FLOAT_TYPE,STRING_TYPE
} DataType;typedef union {int intValue;float floatValue;char *stringValue;
} DataUnion;typedef struct {DataType type;DataUnion data;
} DataHolder;int main() {DataHolder holder;holder.type = INT_TYPE;holder.data.intValue = 42;printf("Integer value: %d\n", holder.data.intValue);holder.type = FLOAT_TYPE;holder.data.floatValue = 3.14;printf("Float value: %.2f\n", holder.data.floatValue);holder.type = STRING_TYPE;holder.data.stringValue = "Hello, World!";printf("String value: %s\n", holder.data.stringValue);return 0;
}

4.注意事项

• 联合成员的互斥性:由于联合的所有成员共享同一块内存,因此在同一时间只能访问一个成员。修改一个成员会覆盖其他成员的数据。

• 内存对齐:编译器可能会对联合进行内存对齐,这可能会影响联合的大小和性能。

• 类型安全:虽然枚举提供了类型安全,但联合的使用可能会导致类型不安全的操作,特别是在不同成员之间进行赋值和访问时。

通过上述详细介绍:

  • 我们了解枚举和联合在C语言中的重要性和灵活性。它们为程序员提供了强大的工具,以处理各种复杂的数据类型和内存管理问题。正确使用枚举和联合可以显著提高程序的性能和可维护性。

快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MYSQL索引的分类和创建

目录 1、聚簇索引和非聚簇索引 tips&#xff1a; 小问题&#xff1a;主键为什么建议使用自增id? 2、普通索引 &#xff08;常规索引&#xff09;(normal) 3、唯一索引&#xff08;UNIQUE &#xff09; 唯一索引和主键的区别&#xff1a; 唯一约束和唯一索引的区别&#…

Robust Depth Enhancement via Polarization Prompt Fusion Tuning

paper&#xff1a;论文地址 code&#xff1a;github项目地址 今天给大家分享一篇2024CVPR上的文章&#xff0c;文章是用偏振做提示学习&#xff0c;做深度估计的。模型架构图如下 这篇博客不是讲这篇论文的内容&#xff0c;感兴趣的自己去看paper&#xff0c;主要是分享环境&…

.NET 一款获取主机远程桌面端口的工具

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

【开源】A066—基于JavaWeb的农产品直卖平台的设计与实现

&#x1f64a;作者简介&#xff1a;在校研究生&#xff0c;拥有计算机专业的研究生开发团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看项目链接获取⬇️&#xff0c;记得注明来意哦~&#x1f339; 赠送计算机毕业设计600个选题ex…

vue3+vite+ts 使用webrtc-streamer播放海康rtsp监控视频

了解webrtc-streamer webrtc-streamer 是一个使用简单机制通过 WebRTC 流式传输视频捕获设备和 RTSP 源的项目&#xff0c;它内置了一个小型的 HTTP server 来对 WebRTC需要的相关接口提供支持。相对于ffmpegflv.js的方案&#xff0c;延迟降低到了0.4秒左右&#xff0c;画面的…

C语言基础六:循环结构及面试上机题

Day06&#xff1a;循环结构 定义 代码的重复执行&#xff0c;就叫做循环 循环的分类 无限循环:其实就是死循环&#xff0c;程序设计中尽量避免无限循环。程序中的无限循环必须可控。有限循环:循环限定循环次数或者循环的条件。 循环的构成 循环条件循环体 当型循环的实现…

树莓集团:探索打造数字影像产业新发展

在当今数字化高速发展的时代背景下&#xff0c;树莓集团始终勇立潮头&#xff0c;坚定地踏上了探索打造产业新发展的非凡征程。 产业生态构建是树莓集团战略布局中的关键一环。集团积极与上下游企业开展广泛而深入的合作&#xff0c;建立起一个互利共赢、协同发展的产业生态系…

Linux 基础环境的开发工具以及使用(下)

1. make / Makefile 自动化构建的工具 1&#xff09;引入 在我们进行一些大型的工程的时候&#xff0c;代码量是极其大&#xff0c;当我们代码在进行一系列的编译的时候&#xff0c;难免会出现一些错误&#xff0c;当我们对错误进行一系列的更改之后&#xff0c;难道我们需要…

ERROR: KeeperErrorCode = NoNode for /hbase/master

原因分析 通过上面的情景模拟&#xff0c;我们可以看到报错的原因在于zookeeper中出现问题&#xff0c;可能是zookeeper中的/hbase/master被删除&#xff0c;或者是在hbase集群启动之后重新安装了zookeeper&#xff0c;导致zookeeper中的/hbase/master节点数据异常。 1. 停止…

【 C语言练习(4)—可自己设置游戏规则的猜数字游戏】

C语言练习&#xff08;4&#xff09; 文章目录 C语言练习&#xff08;4&#xff09;前言题目题目解析结果总结 前言 本次写的猜字游戏有两大优点&#xff0c;可重复玩游戏、可自己设置猜数字规则&#xff0c;通过猜数字游戏锻炼循环体和选择结构体 题目 写一个给定猜数次数&a…

【Vulkan入门】08-CreateRenderPass

目录 先叨叨git信息关键代码TestPipeLine::CreateRenderPass() 先叨叨 上篇已经为Pipeline编写好了程序&#xff08;Shader&#xff09;。接下来要为Pipeline创建RenderPass。 关于RenderPass&#xff0c;在【Vulkan入门】06-Pipeline介绍中已经作了简单的介绍。这里再详细说一…

【GitHub分享】you-get项目

【GitHub分享】you-get 一、介绍二、安装教程三、使用教程四、配置ffmpeg五&#xff0c;卸载 如果大家想要更具体地操作可去开源网站查看手册&#xff0c;这里只是一些简单介绍&#xff0c;但是也够用一般&#xff0c;有什么问题&#xff0c;也可以留言。 一、介绍 you-get是一…

【新】ApiHug官方文档-框架介绍-1/10

ApiHug SDK 扩展 https://apihug.com/zhCN-docs/frameworkApiHug SDK 扩展https://apihug.com/zhCN-docs/framework ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplacehttps://plugins.jetbrains.com/plugin/23534-apihug--api-design-copilot 快速开启 - …

06-标准库开发-STM32-SPI通信协议软件实现

八、SPI协议在STM32中的软件实现 8.1 SPI协议简介 SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外设接口&#xff09;是由Motorola公司开发的一种同步串行数据通信总线。它主要用于微控制器与外设之间的短距离通信&#xff0c;如传感器、显示屏、存储器模块等…

C++ 中的隐式类型转换与强制类型转换详解

在 C 中&#xff0c;类型转换是一个非常重要的概念&#xff0c;涉及从一种数据类型向另一种数据类型的转换。本文将从 隐式类型转换 和 强制类型转换 两个方面详细探讨它们的行为和注意事项&#xff0c;特别是高位和低位的处理。 一、隐式类型转换 隐式类型转换&#xff08;Im…

Redis篇-5--原理篇4--Lua脚本

1、概述 Redis 支持使用 Lua 脚本来执行复杂的操作&#xff0c;这为 Redis 提供了更强的灵活性和性能优化能力。通过 Lua 脚本&#xff0c;你可以在服务器端执行一系列命令&#xff0c;而不需要多次往返客户端与服务器之间&#xff0c;从而减少了网络延迟并提高了效率。此外&a…

Muduo网络库解析---事件循环模块

文章目录 前言ChannelChannel代码Channel.hChannel.cc PollerPoller代码Poller.hPoller.cc EpollPollerEpollPoller代码EpollPoller.hEpollPoller.cc EventLoopEventLoop代码EventLoop.hEventLoop.cc 类图 前言 重写Muduo库实现核心模块的Git仓库 注&#xff1a;本文将重点剖…

全面解析Node.js版本管理工具NVM

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;NVM&#xff08;Node Version Manager&#xff09;是一个强大的工具&#xff0c;用于在不同项目中管理多个Node.js版本。通过NVM&#xff0c;开发者可以轻松切换环境&#xff0c;优化工作流程&#xff0c;并提升…

第十七届山东省职业院校技能大赛 中职组“网络安全”赛项资源任务书样题②

第十七届山东省职业院校技能大赛 中职组“网络安全”赛项资源任务书样题② 模块A 基础设施设置与安全加固(200分)A-1 登录安全加固&#xff08;Windows, Linux&#xff09;A-2 Nginx安全策略&#xff08;Linux&#xff09;A-3日志监控&#xff08;Windows&#xff09;A-4中间件…

常用环境部署(二十四)——Docker部署开源物联网平台Thingsboard

1、Docker和Docker-compose安装 参考网址如下&#xff1a; CENTOS8.0安装DOCKER&DOCKER-COMPOSE以及常见报错解决_centos8安装docker-compose-CSDN博客 2、 Thingsboard安装 &#xff08;1&#xff09;在/home目录下创建docker-compose.yml文件 vim /home/docker-com…