C语言自定义类型——联合体、枚举
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、联合体
- (一)、联合体的声明
- (二)、联合体的特点
- (三)、联合体大小的计算!!
- (四)、联合体的小应用
- 二、枚举
- (一)、枚举的类型声明
- (二)、枚举的类型优点
- (三)、枚举类型的使用
- 总结
前言
提示:这里可以添加本文要记录的大概内容:
提示:以下是本篇文章正文内容,下面案例可供参考
本文主要介绍了C语言中自定义模型的剩下两种类型——联合体和枚举。
一、联合体
(一)、联合体的声明
- 联合体的关键字为union,它的声明跟结构体类型,联合体也是由一个或者多个成员构成,这些成员可以选择不同的类型。但是编译器只为最大的成员分配足够的空间。因为联合体所有的成员共用一块内存空间,所有联合体也叫做:共用体
- 下面是联合体的一段声明和定义变量的代码:
#include<stdio.h>
union Un
{
char c;
int i;
};
int main()
{
//联合体变量的定义,并初始化
union Un un={0};}
(二)、联合体的特点
- 联合体最大的特点就是联合体的成员共用一块内存空间,这样一个联合变量的大小,至少是最大成员的大小(因为联合体至少得有能力保存最大的那个成员)
以代码来验证咱们上面的观点:
#include<stdio.h>
union Un
{
char c;
int i;
};
int main()
{
union Un un ={0};
printf("%p\n",&(un.i));
printf("%p\n",&(un.c));
printf("%p\n",&(un));
return 0;
}
运行结果如下:
从上面运行结果我们可以看出:联合体的成员确实共用一块内存空间,因为它们的起始地址都是一样的。
- 我们给联合体其中一个成员赋值,其他成员的值也跟着变化。
#include<stdio.h>
union Un
{
char c;
int i;
};
int main()
{
union Un un ={0};
un.i=0x11223344;
un.c=0x55;
printf("%x\n",un.i);
}
运行结果如下:
我们可以看出我们通过改变结构体成员c的值间接性改变了成员i的值(从原来的0x11223344->0x11223355)
(三)、联合体大小的计算!!
- 要计算联合体的大小我们要了解以下两条规则:
联合体的大小至少是最大成员的大小;
当最大成员的大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍; - 我们分析一下下面代码中联合体的大小:
#include <stdio.h>union Un1{char c[5];int i;};union Un2{short c[7];int i;};int main(){printf("%d\n", sizeof(union Un1));printf("%d\n", sizeof(union Un2));return 0;}
运行结果如下:
我们从上面特点知道,联合体的大小至少是最大成员的大小,且必须是成员最大对齐数的整数倍。对于结构体Un1来说,最大成员为c,它的大小是5个字节,而最大对齐数是i的对齐数为4,故而应为4的倍数,所以我们应该浪费3个字节,最终Un1结构体的大小为8个字节;对于结构体Un2来说,最大成员为c,它的大小为14个字节,而最大对齐数是i的对齐数为4,故而应为4的倍数,所以我们应该浪费2个字节,最终Un2结构体的大小为8个字节。
(四)、联合体的小应用
- 使用联合体可以节省空间:
咱们以下面一个例子来说明:
比如,我们要搞一个活动,要上线一个礼品兑换单,礼品兑换单中有三种商品:图书、杯子、衬衫。
每种商品都有:库存量、价格、商品类型和商品类型相关的其他信息;例如图书还有的属性:书名、作者、页数;杯子还有的属性:设计;衬衫还有的属性:设计、可选颜色、可选尺寸。
如果我们不考虑很多的话,可以直接粗暴地定义结构体直接将所有属性囊括即可:
struct gift_list
{
//公共地属性
int stock_number;//库存量
double price;//定价
int item_type;//商品类型//特殊属性:
char title[20];//书名
char author[20];//作者
int num_pages;//页数int design[30];//设计
int colors;//颜色
int sizes;//尺寸
}
这样我们所设置地结构体就涵盖了所有属性,要用那块属性地话直接调用即可,但是这样简单粗暴地做法就会使得结构体的大小偏大,比较浪费内存。因为对于礼品兑换单中的商品来说,我们只有部分属性是常用的,有几种属性没有用到
例如对于商品是图书来说的话,design、colors、sizes属性就没有用到。
考虑到这个情况我们可以引进联合体来节省空间,即把公共属性单独列出来,剩余各种商品的本身属性就用联合体给联合起来,(联合体最大的特点是所有成员公用一块内存空间)这样就可以节省内存空间,提高空间利用率
具体实现礼品兑换单的声明如下:
struct gift_list
{
//公共地属性
int stock_number;//库存量
double price;//定价
int item_type;//商品类型union
{
struct
{
char title[20];//书名
char author[20];//作者
int num_pages;//页数
}book;//书的特殊属性
struct
{
int design[30];//设计
}mug;//杯子的特殊属性
struct
{
int design[30];//设计
int colors;//颜色
int sizes;//尺寸
}shirt;//衬衫的特殊属性
}item;//特殊属性
};
- 联合体可以用来判断机器小大端字节序。
前面我们写的判断大小端字节序的代码为:
#include<stdio.h>
int main()
{int a = 1;//0x 00 00 00 01if (*((char*)&a) == 1){printf("小端\n");}else{printf("大端\n");}
}
而我们可以充分利用联合体的内存分配特点,联合体的成员共有一块内存空间,修改代码如下:
#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");}
}
这样会使得代码更加简单好理解,少去了取地址和强转类型的操作。
二、枚举
(一)、枚举的类型声明
- 我们都知道枚举顾名思义就是一 一地列举,把可能地值一一地给列出来
- 枚举地关键字是enum,我们以星期天为例来进行枚举地声明
#include<stdio.h>
enum Day//星期
{Mon,Tues,Wed,Thur,Fri,Sat,Sun
}D;
int main()
{printf("%d\n",Mon);printf("%d\n",Tues);printf("%d\n",Wed);}
运行结果如下:
枚举中成员的取值,默认从1开始,依次递增1,当然也可以手动赋值。
以颜色为例:
#include<stdio.h>
enum
{
RED=2,
GREEN=4,
BLUE=8
};
int main()
{
printf("%d\n",RED);
printf("%d\n",GREEN);
printf("%d\n",BLUE);
}
运行结果如下:
(二)、枚举的类型优点
我们都知道,定义常量的话可以用#define来实现,那我们用枚举的优点是什么呢?
- 增加代码的可读性和可维护性
- 和#define定义的标识符相比较枚举具有类型检查,更加严谨
- 便于调试,预处理阶段会删除#define定义的符号
- 使用方便,一次可以定义多个变量
- 枚举变量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用。
(三)、枚举类型的使用
- 咱们以构造一个计算器为例来阐述一下枚举的使用
原先我们设置的计算器为:
void meau()
{printf("*****************************\n");printf("****1.ADD 2.SUB ******\n");printf("****3.MUL 4.DIV ******\n");printf("****0.Exit ******\n");printf("*****************************\n");printf("*****************************\n");}
int aDD(int x, int y)
{return x + y;
}
int sUB(int x, int y)
{return x - y;
}
int mUL(int x, int y)
{return x * y;
}
int dIV(int x, int y)
{return x / y;
}
int main()
{int input=0;int a = 0, b = 0;do {int result = 0;meau();printf("请选择->:\n");scanf("%d", &input);printf("请输入要进行操作的两个数:\n");scanf("%d %d", &a, &b);switch (input){case 1:result = aDD(a, b);printf("加法的运算结果为:%d\n", result);break;case 2:result = sUB(a, b);printf("减法的运算结果为:%d\n", result);break;case 3:result = mUL(a, b);printf("乘法的运算结果为:%d\n", result);break;case 4:result = dIV(a, b);printf("除法的运算结果为:%d\n", result);break;case 0:printf("退出运算\n");exit(-1);break;default:printf("输入错误,请重新输入\n");}} while(input);
}
我们在switch中还是用数字0,1,2,3,4来做选择,不太直观。
而利用上枚举类型后我们可以修改代码:
#include<stdio.h>
void meau()
{printf("*****************************\n");printf("****1.ADD 2.SUB ******\n");printf("****3.MUL 4.DIV ******\n");printf("****0.Exit ******\n");printf("*****************************\n");printf("*****************************\n");}
enum Option//更加直观
{Exit,ADD,SUB,MUL,DIV
};int aDD(int x, int y)
{return x + y;
}
int sUB(int x, int y)
{return x - y;
}
int mUL(int x, int y)
{return x * y;
}
int dIV(int x, int y)
{return x / y;
}
int main()
{int input=0;int a = 0, b = 0;do {int result = 0;meau();printf("请选择->:\n");scanf("%d", &input);printf("请输入要进行操作的两个数:\n");scanf("%d %d", &a, &b);switch (input){case ADD:result = aDD(a, b);printf("加法的运算结果为:%d\n", result);break;case SUB:result = sUB(a, b);printf("减法的运算结果为:%d\n", result);break;case MUL:result = mUL(a, b);printf("乘法的运算结果为:%d\n", result);break;case DIV:result = dIV(a, b);printf("除法的运算结果为:%d\n", result);break;case Exit:printf("退出运算\n");exit(-1);break;default:printf("输入错误,请重新输入\n");}} while(input);}
运行结果如下:
我们在代码中充分利用了枚举类型,这样增加代码的可读性与维护性,会让使用者更加直观、清晰明了,这就是枚举的重要使用作用。
总结
本文主要介绍了C语言中自定义类型的剩余两种——联合体和枚举类型,如有错误,请批评指正,感谢支持
相关文章:

C语言自定义类型——联合体、枚举
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、联合体(一)、联合体的声明(二)、联合体的特点(三)、联合体大小的计算!&a…...
【trition-server】pytorch 文档:使用 Triton 提供 Torch-TensorRT 模型
Serving a Torch-TensorRT model with Triton pytorch 的官方文档: Serving a Torch-TensorRT model with Triton 在有关机器学习基础设施的讨论中,优化和部署是密不可分的。一旦完成网络级优化以获得最大性能,下一步就是部署它。 然而,提供这种优化模型也有其自身的一系列…...
wps 表格如何实现vlookup高级模糊搜索
一、VLOOKUP 模糊搜索 在 WPS 表格中,可以通过使用 VLOOKUP 函数和通配符来实现高级模糊搜索。这里有一个具体的示例来帮助你理解如何进行这些操作。 示例:实现 VLOOKUP 高级模糊搜索 假设我们有以下数据集: AB产品编号产品名称001苹果00…...

第一天(点亮led灯+led灯闪烁)——Arduino uno R3 学习之旅
常识: 一般智能手机的额定工作电流大约为200mA Arduino Uno板上I/0(输入/输出)引脚最大输出电流为40 mA Uno板控制器总的输出电流为200 mA 点亮LED灯 发光二极管介绍 发光二极管(Light Emitting Diode,简称LED)是一种能够将电能转化为光能的固态的半导体器件…...

【C++题解】1561. 买木头
问题:1561. 买木头 类型:省赛、数组问题、二分答案、贪心、2015江苏省青少年信息学奥林匹克竞赛复赛 题目描述: 有 n 个木材供应商,每个供货商有长度相同一定数量的木头。长木头可以锯短,但短木头不能接长。有一个客…...
解决android native包webview,webview中的请求blocked by CORS policy
在stack overflow查,差不多查到的都是些webView.getSettings().setxxx,没用。在github上找别的类似的android native包webview运行pwa的项目,把它们的webView.getSettings().setxxx全搬过来,写了有一页多,一个有用的都…...

链篦机回转窑球团生产工艺
生球在回转窑氧化焙烧,回转窑头部设有燃烧器,燃料可以采用气体、固体、液体。 来自环冷机一冷却段的高温废气作为二次风进入窑内参与燃烧,烧成成品球进入环冷机。 环冷机采用鼓风冷却,热风风箱分为四段: 一段气体引至…...

查看电脑ip地址快捷键是什么?是哪个
在网络世界中,IP地址是每个网络设备的唯一标识,无论是我们的电脑、手机还是其他联网设备,都需要一个独特的IP地址来进行通讯。在日常生活和工作中,我们有时需要查看电脑的IP地址,以便进行网络设置、故障排查或远程连接…...
面试专区|【54道Spring Cloud高频题整理(附答案背诵版)】
什么是Spring Cloud? Spring Cloud是一个基于Spring Boot的开源框架,它提供了在分布式系统中集成各种服务治理功能的工具,如配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态等。其主要目…...

Shopee(虾皮)怎么获取流量?
店铺流量的高低会直接关联到卖家店铺单量,也关系到一个店铺的营业情况和利润,那么Shopee的流量从哪里来呢? Shopee的平台流量可分为五个部分: 1.自然流量 2.关键字广告流量 3.平台活动流量 4.营销流量 5.粉丝流量 怎么提升…...

Java启动虚拟机默认字符集编码
-Dfile.encodingUTF-8 java程序启动默认字符集编码参数 // 这里会创建一个Charset.defaultCharset().name()的流,在Windows命令行窗口启动,会出现字符编码为GBK的情况 // 导致乱码输入、输出都会有影响 // 解决办法流的读取指定编码new InputStreamRead…...
【单片机编程模式】状态机编程
状态机编程是一种编程模式,它基于有限状态机(Finite State Machine,简称FSM)的概念。以下是状态机编程的清晰解释,分点表示和归纳: 基本概念: 状态机是一个有向图形,由一组节点&…...

IPSS模块怎么安装到VOS服务器的,到底有没有效果,是不是能大幅度提升VOS3000安全性呢
由于VOS的普及性,不得不承认VOS确实是非常优秀的软交换,但是很多客户在使用过程中都会遇到各种安全问题,比如话费被盗用了,历史话单一堆的非法呼叫话单,严重的影响到了话务安全,并不是那点话费的事了&#…...
C++ STL容器:序列式容器-堆pirority_queue
摘要: CC STL(Standard Template Library,标准模板库)在C编程中的重要性不容忽视,STL提供了一系列容器、迭代器、算法和函数对象,这些组件极大地提高了C程序的开发效率和代码质量。 STL 容器 分为 2 大类 …...

ECharts在最新版本中使用getInstanceByDom报错处理
引用问题导致报错 如果按如下引用的话,会报错 import echarts from “echarts/lib/echarts”; 原因 在 ECharts 的之前版本中,默认导出了一个名为 echarts 的对象,所以使用 import echarts from “echarts” 是没有问题的。但是在 ECharts …...

利用C语言实现三子棋游戏
文章目录 1.游戏界面2.游戏内容2.1 棋盘类型2.2棋盘的初始化2.3 打印棋盘的界面展示 3.游戏操作3.1 玩家操作3.2 电脑操作3.3 胜负判定 4.代码整合 1.游戏界面 无论写任何程序,我们都需要先去了解它的大概框架,这里我们先把它的初始界面写出来。一个游戏…...

大学教师门诊预约小程序-计算机毕业设计源码73068
摘要 在当今数字化、信息化的浪潮中,大学校园的服务管理正朝着智能化、便捷化的方向迈进。为了优化大学教师的医疗体验,提升门诊预约的效率和便捷性,我们基于Spring Boot框架设计并实现了一款大学教师门诊预约小程序。该小程序不仅提供了传统…...
Python PyCryptodome库介绍与实例
Python PyCryptodome库介绍与实例 1. 安装2. 基本概念3. 使用场景和示例代码3.1 对称加密 - AES3.2 非对称加密 - RSA3.3 哈希函数 - SHA2563.4 消息认证码 - HMAC 4. 总结 PyCryptodome是一个强大的Python加密库,提供了各种加密算法和工具。本文将介绍PyCryptodome的基本概念和…...
《框架封装者 · 自定义初始化事件》
📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…...
ActiViz实战:使用vtkImageClip和vtkImageActor根据滑动条来显示当前图像数据切面
文章目录 一、效果预览二、代码实现三、源码地址一、效果预览 ActiViz实现图像数据切面显示 二、代码实现 public partial class Form1 : Form {private vtkRenderWindowInteractor _interactor;private vtkRenderer _renderer...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...