C语言 联合和枚举

目录

  • 1. 联合体
    • 1.1 联合体类型的声明
    • 1.2 联合体变量的创建
    • 1.3 联合体的特点
    • 1.4 联合体在内存中的存储
    • 1.5 联合体使用举例
  • 2. 枚举类型
    • 2.1 枚举类型的声明
    • 2.2 枚举变量的创建和初始化
    • 2.3 枚举类型的大小
    • 2.4 枚举类型的优点


正文开始

上次我们通过《C语言 结构体详解》学习了结构体的相关知识,今天我们来学习一下结构体的亲戚联合枚举,它们同结构体一样,都是C语言中的自定义类型,由一个或多个成员构成。因为本文所讲内容与结构体有很多相似之处,所以先学习结构体再食用本文更佳呦~

1. 联合体

1.1 联合体类型的声明

联合体的声明和结构体的声明类似:

union Un_name
{member-list;
};

其中:

  • union用来声明这是一个联合体
  • Un_name是联合体名
  • member-list为成员列表

1.2 联合体变量的创建

#include <stdio.h>//联合体类型的声明
union Un
{char c;int i;
};int main()
{//联合变量的定义union Un un = { 0 };un.i = 3;un.c = 'a';return 0;
}

联合体变量的创建以及初始化等与结构体基本相同,这里不再赘述。

1.3 联合体的特点

联合体的声明与结构体基本相同,那两者有什么区别呢?我们都知道结构体在内存中的存储符合内存对齐规则,这样做的好处就是增强了性能,但是却浪费了空间。而联合体主打一个节省空间,原因如下:

  • 联合体成员共用一块内存(所以联合体又叫共用体)
  • 联合体大小至少为最大成员的大小,这样才能确保能放下所有数据

我们写个代码验证一下:

# include <stdio.h>union Un
{char c;int i;
};int main()
{union Un un = { 0 };printf("%p\n", &(un.c));printf("%p\n", &(un.i));printf("%p\n", &un);return 0;
}

运行结果:
在这里插入图片描述
由此我们验证了,联合体成员共用一块内存。

1.4 联合体在内存中的存储

联合体成员共用一块内存,那他们究竟是怎么存储的呢?

  • 联合体的大小至少是最大成员的大小
  • 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍
  • 由于联合体成员共用同一块内存,所以一般独立使用各个联合体成员

例如:

#include <stdio.h>union Un1
{char c[5];int i;
};union Un2
{short c[7];int i;
};int main()
{printf("Un1 -> %zd\n", sizeof(union Un1));printf("Un2 -> %zd\n", sizeof(union Un2));return 0;
}

在内存中的存储情况如下:
在这里插入图片描述

上图可以看出,整个联合体的大小满足两个条件:

  • 至少是最大成员的大小
  • 大小要对齐到最大对齐数的整数倍。例如 Un1 最大的对齐数是4,所以总大小补齐为8;Un2 最大的对齐数是4,所以总大小补齐为16

运行验证一下:
在这里插入图片描述

1.5 联合体使用举例

假如我们需要记录图书、杯子、衬衫三种商品的数据,每一种商品都有:库存量、价格、商品类型和一些其他信息:

  • 图书:书名、作者、页数
  • 杯子:设计
  • 衬衫:设计、颜色、尺寸

如果我们使用结构体书写:

struct Product
{//共有属性int stock_number;//库存量double price;//价格int item_type;//商品类型//特有属性char title[20];//书名char author[20];//作者int num_page;//页数char design[30];//设计int colors;//颜色int sizes;//尺寸
};

这样写似乎没有什么问题,但一个结构中包含了所有商品的各种属性,当我们描述图书的时候,就用不上设计、颜色和设计,这样就使得结构体的大小偏大,比较浪费内存。所以我们可以使用联合体书写:

struct Product
{//共有属性int stock_number;//库存量double price;//价格int item_type;//商品类型union{struct{char title[20];//书名char author[20];//作者int num_page;//页数}book;//图书struct{char design[30];//设计}mug;//杯子struct{char design[30];//设计int colors;//颜色int sizes;//尺寸}shirt;//衬衫}item;
};

这样就相当于把三种商品的特有属性共存在一块内存中,使用时也相互独立,这样保证了正常使用,也能够节省空间。

2. 枚举类型

枚举,顾名思义就是一个一个列举,比如我们现实生活中:

  • 星期一到定期日可以列举
  • 性别可以列举
  • 月份可以列举

2.1 枚举类型的声明

枚举类型的声明与结构体类似:

enum Enum_name
{value1,value2,value3,//...
};
  • 使用关键字enum来声明枚举类型
  • Enum_name为枚举名
  • {}中的内容为枚举类型的可能取值,称作枚举常量。
  • 枚举常量之间由,隔开
  • 枚举常量都是有初始值的,默认从0开始,步长为1依次递增。
  • 给定枚举常量的值,就类似于#define定义标识符,只不过#define是在预处理阶段完成的,枚举类型是在编译阶段完成的

例如:

enum Color
{RED,//0GREEN,//1BLUE//2
};

我们也在声明枚举类型时赋值:

enum Color1
{RED=3,//3GREEN,//4BLUE//5
};enum Color2
{RED=3,//3GREEN=5,//5BLUE=7//7
};enum Color3
{RED,//0GREEN=3,//3BLUE//4
};

对于枚举类型的理解:
声明一个枚举,就是定义了一种类型,这种类型的可能取值就是枚举常量的值

2.2 枚举变量的创建和初始化

枚举变量的创建和初始化与结构体类似,这里只做演示,详情不再赘述。

enum Color
{RED,//0GREEN,//1BLUE//2
};int main()
{enum Color red = 0;//等同于RED//定义了一个类型为 enum Color 的枚举变量red//变量 red 的值为0,也就是REDreturn 0;
}

2.3 枚举类型的大小

枚举是一种数据类型,它的可能取值就使枚举常量的值,枚举常量本质都是整型,也就是说,不管是枚举类型,还是枚举变量,亦或是枚举常量,它们的大小都与整型相同,都是4个字节,下面我们验证一下:

#include <stdio.h>enum Color
{RED,GREEN,BLUE
};int main()
{enum Color red;printf("%d\n", sizeof(enum Color));//枚举类型printf("%d\n", sizeof(RED));//枚举常量printf("%d\n", sizeof(GREEN));//枚举常量printf("%d\n", sizeof(BLUE));//枚举常量printf("%d\n", sizeof(red));//枚举变量return 0;
}

运行结果:
在这里插入图片描述

2.4 枚举类型的优点

有的人可能会想到,既然都是定义常量,那为什么不用#define呢?

因为枚举有以下优点:

  • 枚举将标识符集中起来,不像是#define那样分散开,增加了代码的可读性和可维护性
  • 枚举类型定义的标识符有类型检查(是枚举类型),更为严谨,而#define没有(直接替换)
  • 便与调试,预处理阶段会删除#define定义的符号
  • 使用方便,一次可以定义多个常量
  • 枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用,而#define定义的标识符是全部都直接替换


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

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

相关文章

在拥有多个同名称密码的ap环境中,如何连接到指定信道或mac的ap路由器?

在给客户做ESP32-C3入墙开关项目时&#xff0c;客户问&#xff1a;在拥有多个同名称密码的ap环境中&#xff0c;如何连接到指定信道或mac的ap路由器&#xff1f;针对这个问题&#xff0c;启明云端工程师给出下面解决方法。 1、将wifi_sta_config_t配置中的channel配置为该信道…

GZIP文件格式解析和Inflate静态Huffman解压缩

GZIP是封装了Deflate压缩的格式文件&#xff1b;Deflate使用了无压缩、HuffmanLZ77进行压缩&#xff1b;解压是Inflate&#xff0c;Huffman包括静态Huffman压缩和动态Huffman压缩两种模式。 Java语言实现了GZIP格式解析、Inflate的静态Huffman解压缩、CRC32校验 算法。 gzip文…

使用Maven对Java独立应用程序进行编译打包

一、 安装Maven 1.解压&#xff0c;移动安装包 sudo tar -zxf ~/apache-maven-3.9.6-bin.tar.gz -C /usr/local/ cd /usr/local/ sudo mv apache-maven-3.9.6/ ./maven-3.9.6 sudo chown -R qiangzi ./maven-3.9.6 二、Java应用程序代码 1.版本信息&#xff1a; Spark-2.1…

jsp校园商城派送系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 校园商城派送系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统采用serlvetdaobean mvc 模式&#xff0c;系统主要采用B/S模式 开发。开发环境为TOMCAT7.0,Myeclipse8.…

Leetcode—2079. 给植物浇水【中等】

2024每日刷题&#xff08;130&#xff09; Leetcode—2079. 给植物浇水 实现代码 class Solution { public:int wateringPlants(vector<int>& plants, int capacity) {int ans 0;int step 0;int cap capacity;bool flag false;for(int i 0; i < plants.siz…

求知导刊-知网收录//旬刊//如何投稿?

求知导刊-知网收录//旬刊//如何投稿&#xff1f; 《求知导刊》栏目设置 理论探索、课堂教学、教改课改、教育管理、教师教育、教学案例、学科进展、学术论坛。 《求知导刊》征稿对象&#xff1a; 全国科技工作者、教育工作者&#xff0c;各级科技与教育部门的领导者以及管理…

一文读懂 SOLID 原则

大家好&#xff0c;我是孔令飞&#xff0c;字节跳动云原生开发专家、前腾讯云原生技术专家、云原生实战营 知识星球星主、《企业级 Go 项目开发实战》作者。欢迎关注我的公众号【令飞编程】&#xff0c;Go、云原生、AI 领域技术干货不错过。 在 Go 项目开发中&#xff0c;你经常…

北邮22级信通院DSP:实验三(1):FFT变换、IFFT变换(附每步8点变换蝶形图)保姆级讲解+用C++程序实现复数域的FFT变换和IFFT变换+C++中的chrono头文件讲解

北邮22信通一枚~ 跟随课程进度更新北邮信通院DSP的笔记、代码和文章&#xff0c;欢迎关注~ 获取更多文章&#xff0c;请访问专栏&#xff1a; 北邮22级信通院DSP_青山入墨雨如画的博客-CSDN博客 目录 一、预备知识 1.1 FFT算法 1.2.1由DFT到FFT 1.2.2 基2时域抽选算法 …

Spring+Vue的卓越托管中心管理系统的设计与实现+PPT+论文+讲解+售后

相比于以前的传统手工管理方式&#xff0c;智能化的管理方式可以大幅降低运营人员成本&#xff0c;实现了卓越托管中心管理系统的标准化、制度化、程序化的管理&#xff0c;有效地防止了卓越托管中心管理系统的随意管理&#xff0c;提高了信息的处理速度和精确度&#xff0c;能…

【LAMMPS学习】八、基础知识(5.11)磁自旋

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

最新版Ceph( Reef版本)块存储简单对接k8s

当前ceph 你的ceph集群上执行 1.创建名为k8s-rbd 的存储池 ceph osd pool create k8s-rbd 64 642.初始化 rbd pool init k8s-rbd3 创建k8s访问块设备的认证用户 ceph auth get-or-create client.kubernetes mon profile rbd osd profile rbd poolk8s-rbd部署 ceph-rbd-csi c…

Nginx配置Https缺少SSL模块

1、Linux下Nginx配置https nginx下载和安装此处就忽略&#xff0c;可自行百度 1.1、配置https 打开nginx配置文件 vim /opt/app/nginx/conf/nginx.conf相关https配置 server {listen 443 ssl; #开放端口server_name echarts.net;#域名#redirect to https#ssl on; #旧版#ssl证…

c#实现音乐的“vip播放功能”

文章目录 前言1. c#窗体2. 功能3. 具体实现3.1 添加文件3.2 音乐播放3.3 其他功能 4. 整体代码和窗口5. 依赖的第三方库 前言 最近在QQ音乐里重温周杰伦的歌&#xff0c;觉得好听到耳朵怀孕&#xff0c;兴起想要下载下来反复听&#xff0c;发现QQ音乐VIP歌曲下载下来的格式居然…

微信小程序 手机号授权登录

手机号授权登录 效果展示 这里面用的是 uni-app 官方的登录 他支持多端发布 https://zh.uniapp.dcloud.io/api/plugins/login.html#loginhttps://zh.uniapp.dcloud.io/api/plugins/login.html#login 下面是代码 <template><!-- 授权按钮 --><button v-if&quo…

1984. 学生分数的最小差值C++

给你一个 下标从 0 开始 的整数数组 nums &#xff0c;其中 nums[i] 表示第 i 名学生的分数。另给你一个整数 k 。 从数组中选出任意 k 名学生的分数&#xff0c;使这 k 个分数间 最高分 和 最低分 的 差值 达到 最小化 。 返回可能的 最小差值 。 示例 1&#xff1a; 输入&…

硬件设计细节1-缓冲驱动器使用注意事项

目录 一、缓冲驱动器二、实例分析1.硬件结构2.问题描述3.原因分析4.原因定位 三、结论 一、缓冲驱动器 缓冲驱动器通常用于隔离、电平转换等应用场景。在使用时&#xff0c;需要关注的点较多&#xff0c;如电平范围、频率范围、延时、控制方式、方向以及输入输出状态。通常&am…

Git === Git概述 Git安装

第1章 Git概述 Git是一个免费的、开源的分布式版本控制系统&#xff0c;可以快速高效地处理从小型到大型的各种项目。 Git易于学习&#xff0c;占地面积小&#xff0c;性能极快。 它具有廉价的本地库&#xff0c;方便的暂存区域和多个工作流分支等特性。其性能优于Subversion…

配置好Maven后本地仓库不自动加载以及创建Maven报错的解决方法

先退出到全局模式再点击All Settings 点击maven 修改Maven home path修改了这个local不同步 点击Flie中的Module 然后选择maven 点击next设置需要存放的位置以及组名 然后报错 报错误的原因是因为maven版本太高和与你使用的IDEA版本不兼容 将maven的版本改为3.6并修改环境变量 …

【C++】从零开始认识多态

送给大家一句话&#xff1a; 一个犹豫不决的灵魂&#xff0c;奋起抗击无穷的忧患&#xff0c;而内心又矛盾重重&#xff0c;真实生活就是如此。 ​​​​ – 詹姆斯・乔伊斯 《尤利西斯》 _φ(*&#xffe3;ω&#xffe3;)&#xff89;_φ(*&#xffe3;ω&#xffe3;)&…

ReactFlow的ReactFlow实例事件传参undefined处理状态切换

1.问题 ReactFlow的ReactFlow实例有些事件我们在不同的状态下并不需要&#xff0c;而且有时候传参会出现其它渲染效果&#xff0c;比如只读状态下我们不想要拖拉拽onEdgesChange连线重连或删除的功能。 2.思路 事件名称类型默认值onEdgesChange(changes: EdgeChange[]) >…