C++系列第七篇 数据类型下篇 - 复合类型(结构体、共用体及枚举)

系列文章

C++ 系列 前篇 为什么学习C++ 及学习计划-CSDN博客

C++ 系列 第一篇 开发环境搭建(WSL 方向)-CSDN博客

C++ 系列 第二篇 你真的了解C++吗?本篇带你走进C++的世界-CSDN博客

C++ 系列 第三篇 C++程序的基本结构-CSDN博客

C++ 系列 第四篇 C++ 数据类型上篇—基本类型-CSDN博客

C++ 系列 第五篇 C++ 算术运算符及类型转换-CSDN博客

C++系列第六篇 数据类型下篇 - 复合类型(数组及字符串)-CSDN博客

前言

          本章主要进行结构体、共用体及枚举的总结,在C语言项目中, 如果针对编程有规范的话,或者说公司不止要求你实现功能即可,还要代码可读、可维护、节省空间,那这三类结构的使用频率应该比单独的数组或者字符串高,为什么呢,因为结构起了一个整理的作用,C++的类从个人理解其实是结构的延伸,而枚举则是程序可读,可维护必不可少的一个数据类型, 共用体则可以在一定条件下起到节省内存的效果。

结构体

        假设要存储有关员工的信息,则可能需要存储他(她)的姓名、工资、身高、体重、入职时间等。希望有一种数据格式可以将所有这些信息存储在一个单元中。数组不能完成这项任务,因为虽然数组可以存储多个元素,但所有元素的类型必须相同。也就是说,一个数组可以存储 20个int,另一个数组可以存储 10个float,但同一个数组不能在一些元素中存储int,在另一些元素中存储float。

        结构是一种比数组更灵活的数据格式,因为同一个结构可以存储多种类型的数据,这使得能够将有关员工的信息放在一个结构中,从而将数据的表示合并到一起。如果要跟踪整个公司的员工,则可以使用结构数组。结构也是 C++ 类的基石。学习有关结构的知识将使我们离C++的核心 OOP 更近。

        结构是用户定义的类型,而结构声明定义了这种类型的数据属性。定义了类型后,便可以创建这种类型的变量。因此创建结构包括两步。首先,定义结构描述--它描述并标记了能够存储在结构中的各种数据类型。然后按描述创建结构变量(结构数据对象)。 

结构体声明及变量定义

        如下所示,我们使用struct employee 声明了一个雇员的结构体 ,并使用该声明在 main 函数中定义了两个该结构体类型的变量 employee1 和employee2,并分别给两个结构体变量进行了赋值输出。

         结构体声明整体组成如下,主要由 关键字,声明的名称,闭合的大括号,大括号中的成员变量及 分号结尾组成。

        结构体变量的定义则有两种方式,一个是 C-风格的定义 ,"struct employee employee1;" 这样;另一种则是C++风格,省略 struct 关键字 ,直接  "employee employee1;" 这样。

       使用(.)来访问各个成员。例如,employee1.name指的是结构的name成员。通过成员名能够访问结构的成员,就像通过索引能够访问数组的元素一样。由于 name成员被声明为字符数组类型,因此 employee1.name 相当于是 字符数组变量,可以像使用常规 字符数组变量那样来使用它们。总之,employee1是一个结构,而employee1.name 是一个字符数组变量。顺便说一句,访问类成员函数(如cingetline())的方式是从访问结构成员变量的方式衍生而来的。

结构体使用的一些注意点

        声明位置 

        结构声明的位置很重要。有三种选择。可以将声明放在函数中;可以将声明放到 cpp 文件种,但是在使用函数的前面; 也可以放在 头文件中。 三种放置位置,决定了该结构声明可以生效的位置, 如果是在函数中,则只有本函数内可以使用,如果在函数外,但是在cpp 文件中,则该源码文件 内都可以使用,在头文件中,则能引用到该头文件的位置都可以使用。

        我们在上边的例程中采用的是 源码文件中定义的方式,位于函数外面的声明被称为外部声明。一般推荐在源码文件或者根据实际情况在头文件中声明。

        但是一定要注意,我们这里说的是声明而非定义,在实际的编码中,包括设计指导中,都会有意的避免外部定义(全局定义),我们一定要区分声明和定义。

        结构体变量初始化

        同其它变量一样,有普通初始化方式和C++11引入的列表初始化方式,不过在结构中看着基本都一样。

       如下所示,使用初始化 和上边示例中复制后输出是一致的, employee1 使用了 普通初始化方式,employee2 使用了列表初始化省略等于号的初始化方式,都可以正常初始化成功,列表初始化再次强调下特殊点,一是不允许缩窄,具体情况就不详细介绍了,之前都说过,二是空{},相当于初始化为了全0。 

结构体数组 

        与C语言一样,C++也允许指定占用特定位数的结构成员,这使得创建与某个硬件设备上的寄存器对应的数据结构非常方便。字段的类型应为整型或枚举(后边会介绍),接下来是冒号,冒号后面是一个数字,它指定了使用的位数。

        如下示例中,bits 结构体变量,包含两个int 类型的位成员变量,起成员变量赋值和正常结构体成员变量赋值无异。同时值得注意的是,虽然看着 是 两个int 位成员变量,但是实际在内存中只占用了,一个int 型大小,所以 抛开 结构对齐 的内存不说,包含位成员的结构体总大小,实际要看总共位所占用的基本类型的个数。

        在上边示例中,还有一个需要注意的点是,我们结构体没有名称声明,直接进行的定义 ,bits直接是一个变量,在实际编程中很少有这么用的,在函数中归纳一些变量,在其它地方不会用到时会这么用,知道有这么个东西进行。

共用体

        共用体使用 

        共用体(union)是一种数据格式,它能够存储不同的数据类型,但只能同时存储其中的一种类型。也就是说,结构可以同时存储 int、long 和 double 或者 复合类型,当同时,只能有一个类型在代码上下文是有含义的。

        如下示例中,union id 为一个共用体,内部变量为一个int 型, 和一个字符数组,字符数组的宽度为3。 定义一个 id 类型的 共用体变量 id_v , 通过sizeof 计算可知 ,该共用体实占内存为4,即共用体实际占用的内存为功能体内占用内存最大的变量 所占用的内存。较小的变量复用了该内存中的一部分。

        我们给共用体中的int 型元素赋值为65,65 对应的ASCII 字符为 'A', 从上边内存复用的角度,我们输出 字符数组的最低元素,可以看到 确实是一个 'A'。 这样的话,在实际编程中, 比如有一个需求是需要存储某个人的ID,但是有的id 是整型的,有得id 是 字符形式得,那就可以使用这种结构起到节省内存的效果。虽然现在服务器内存都比较充足,但是在一些嵌入式设备或者体量比较大量的数据应用中,使用共用体是必不可少的。

       匿名共用体

        我们实际使用中,很少共用体单独去定义一个类型,基本都是包含在结构体里边,在结构体里边的话,我们最常用的就是使用匿名共用体,如下方式 ,person 结构体中的 共用体是没有名称的,所以调用共用体内的变量,直接像调用结构体中的变量一样就行。

枚举

       枚举使用

         可以使用enum关键字来定义枚举类型 。枚举提供了另一种创建符号常量的方式,这种方式可以代替const。它还允许定义新类型,但必须按严格的限制进行。使用 enum 的句法与使用结构相似。

        示例中 enum Color 让Color成为新类型的名称,将RED、GREEN、BLUE 等作为符号常量,它们对应整数值0~2。这些常量叫作枚举量(enumerator)。在默认情况下,将整数值赋给枚举量,第一个枚举量的值为0,第二个枚举量的值为1,依次类推。

也可以通过显式地指定整数值来覆盖默认值,后续的枚举量会在指定的枚举量值上一次底层

      枚举的一些限制

         1、枚举 变量在 不强制转换的情况下,只能由枚举量来赋值,如下的赋值时不被允许的

        2、通过强制转换可以给枚举变量赋值枚举量以外的值, 编译不会报错,但是结果是未定义的,即这样使用是不可靠的

        3、枚举的取值范围

        最初,对于枚举来说,只有声明中指出的那些值是有效的。然而,C++现在通过强制类型转换,增加了可赋给枚举变量的合法值。每个枚举都有取值范围(range),通过强制类型转换,可以将取值范围中的任何整数值赋给枚举变量,即使这个值不是枚举值。

        取值范围的定义如下。首先,要找出上限,需要知道枚举量的最大值。找到大于这个最大值的、最小的 2 的幂,将它减去1,得到的便是取值范围的上限。例如,最大值枚举值是 101,在 2 的幂中,比这个数大的最小值为128,因此取值范围的上限为 127。要计算下限,需要知道枚举量的最小值。如果它不小于 0,则取值范围的下限为 0;否则,采用与寻找上限方式相同的方式,但加上负号。例如,如果最小的枚举量为-6,而比它小的、最大的2的幂是-8(加上负号),因此下限为-7。选择用多少空间来存储枚举由编译器决定。对于取值范围较小的枚举,使用一个字节或更少的空间;而对于包含 long 类型值的枚举,则使用4个字节。        

        所以像下边这种是没问题的

       

        以上可以看到枚举有一些列的限制,我们还是应该进行常规枚举使用,比如定义业务相关的符号常量,而不是定义一个新的枚举类型, 如果只是用于定义符号常量的话,枚举可以没有名称。如下示例是一个符号常量的使用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【MATLAB】辛几何模态分解分解+FFT+HHT组合算法

有意向获取代码,请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 辛几何模态分解(CEEMDAN)是一种处理非线性和非平稳信号的适应性信号分解方法。通过在信号中加入白噪声,并多次进行经验模态分解(EMD&#…

2024年度AI投资策略报告:乘AI之风,破明日之浪

今天分享的AI系列深度研究报告:《2024年度AI投资策略报告:乘AI之风,破明日之浪》。 (报告出品方:万联证券) 报告共计:25页 1 需求复苏,政策指引热点驱动AI 赋能助推行业发展 1.1 …

uniapp实战 —— 骨架屏

1. 自动生成骨架屏代码 在微信开发者工具中,预览界面点击生成骨架屏 确定后,会自动打开骨架屏代码文件 pages\index\index.skeleton.wxml 2. 将骨架屏代码转换为vue文件 在项目中新建文件 src\pages\index\components\skeleton.vue 将pages\index\index…

湖南大学-电路与电子学-2021期末A卷★(不含解析)

【写在前面】 电路与电子学好像是从2020级开设的课程,故实际上目前只有2020与2021两个年级考过期末考试。 本份卷子的参考性很高,这是2020级的期末考卷。题目都是很典型的,每一道题都值得仔细研究透。 特别注意:看得懂答案跟写得…

代码随想录算法训练营 ---第六十天

今天是最后一天,也是最后一题了,单调栈的应用,是昨天单调栈的变形题。 第一题: 简介: 本题和昨天的接雨水题可以说是很相似的一题。我们知道做单调栈问题,我们要先明确我们的单调栈是递增还是递减。由题意…

Android studio生成二维码

1.遇到的问题 需要生成一个二维码&#xff0c;可以使用zxing第三方组件&#xff0c;增加依赖。 //生成二维码 implementation com.google.zxing:core:3.4.1 2.代码 展示页面 <ImageViewandroid:id"id/qrCodeImageView"android:layout_width"150dp"an…

Kafka集成springboot

安装kafka&#xff0c;直接到官网下载bin文件&#xff0c;本文使用windows进行使用kafka。 下载之后&#xff0c;第一步&#xff0c;启动zookeeper&#xff1a; zookeeper-server-start.bat ..\..\config\zookeeper.properties 第二步&#xff0c;启动kafka&#xff1a; kafka…

玩转系统|利用HestiaCP自建NS解析及邮局并利用MailGun进行发信

前述 HestiaCP是一个VestaCP分叉来的产物&#xff0c;而同样作为VestaCP分叉来的myVesta也具有类似的功能。VestaCP本身作为一个社区的产区&#xff0c;其仅仅有一个商业插件需要每月付费5USD进行使用&#xff0c;因此为了达到完全开放使用的目的&#xff0c;这里选择使用Hest…

yolov8添加cbam注意力机制

(如果添加的是CBAM&#xff0c;已存在&#xff0c;忽略步骤 1 2 3) 步骤1.创建注意力机制-类 ultralytics/nn/modules/conv.py 步骤2.添加到conv.py文件的头文件里 ultralytics/nn/modules/conv.py 步骤3.添加到 init.py文件的头文件里 ultralytics/nn/modules/init.py…

SD之lora训练

目录 为什么要训练自己的模型 SD模型微调方法 准备素材 1 确定要训练的LoRA类型 2 图片收集 3 图片预处理 4 图片标注 安装Koyha_ss 训练lora 1.准备参数和环境 2.启动训练 使用模型 1 拷贝训练过的lora模型 2 启动SD WebUI进行图像生成 为什么要训练自己的模型 …

redis集群(cluster)笔记

1. 定义&#xff1a; 由于数据量过大&#xff0c;单个Master复制集难以承担&#xff0c;因此需要对多个复制集进行集群&#xff0c;形成水平扩展每个复制集只负责存储整个数据集的一部分&#xff0c;这就是Redis的集群&#xff0c;其作用是提供在多个Redis节点间共享数据的程序…

基于Swin_Transformer的图像超分辨率系统

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 随着科技的不断发展&#xff0c;图像超分辨率技术在计算机视觉领域中变得越来越重要。图像超分辨率是指通过使用计算机算法将低分辨率图像转换为高分辨率图像的过…

111.am40刷机折腾记4-firefly镜像-dp正常显示

1. 平台&#xff1a; rk3399 am40 4g32g 2. 内核&#xff1a;firefly的内核&#xff08;整体镜像&#xff09; 版本&#xff1a; linux4.4.194 3. 交叉编译工具 &#xff1a;暂时不编译 4. 宿主机&#xff1a;ubuntu18.04 5. 需要的素材和资料&#xff1a;boot-am40-202…

Uos打包工具最新

我司中标的桌面端项目&#xff08;electron开发的应用&#xff09;需兼容统信UOS&#xff0c;关键是要发布到应用商店&#xff0c;首先使用了debreateForUos工具进行打包&#xff0c;打包之后也通过了审核上架到了商店&#xff0c;本以为一切都是如此丝滑顺利&#xff0c;但后续…

10个电子工程师常用的测量仪器详解

之前我们聊了电子工程师常用的模电及数电&#xff0c;得到了很多粉丝朋友的追捧&#xff0c;所以今天主要讲讲电子工程师常用的测量仪器&#xff0c;希望对小伙伴们有所帮助&#xff0c;一起来看看吧&#xff01; 1、万用表 万用表是最基本的测量仪器之一&#xff0c;用于测量…

【Linux】cat 命令使用

cat 命令 cat&#xff08;英文全拼&#xff1a;concatenate&#xff09;命令用于连接文件并打印到标准输出设备上。 可以使用cat连接多个文件、创建新文件、将内容附加到现有文件、查看文件内容以及重定向终端或文件中的输出。 cat可用于在不同选项的帮助下格式化文件的输出…

志愿者小程序开发方案详解

志愿者服务小程序有三端&#xff1a;用户端商家端&#xff0c;管理员端&#xff0c;总管理后台。申请成为志愿者&#xff0c;参加志愿者活动&#xff0c;获得积分和服务时长&#xff0c;志愿者服务时长排名&#xff0c;积分可以兑换商品。社区管理员可以管理自己社区的志愿者和…

使用IDM批量下载NASA气象数据

写在前面:因为科研需要&#xff0c;所以需要批量下载NASA数据&#xff0c;但是nasa的文件会每天给一个url链接&#xff0c;手动下载起来很慢&#xff0c;所以特写此篇文章用以教学如何批量下载NASA气象数据 1.下载NASA数据: 首先我们先进入到官网&#xff1a; 官网链接 右上…

海外媒体发稿:软文发稿推广技巧解析超级实用-华媒舍

随着互联网时代的发展&#xff0c;软文发稿成为推广产品与服务的重要手段之一。本文将向大家介绍软文发稿推广的技巧&#xff0c;帮助您更好地利用软文推广商业活动。无论是拥有自己的品牌还是个人创业者&#xff0c;都可以从中受益。 1. 什么是软文&#xff1f; 软文是指以文…