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语言中自定义类型的剩余两种——联合体和枚举类型,如有错误,请批评指正,感谢支持

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

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

相关文章

二维树状数组区域查询

落谷4514 过关代码如下 #define _CRT_SECURE_NO_WARNINGS #include<bits/stdc.h> using namespace std; //#define int long longconst int N 2050; int t1[N][N], t2[N][N], t3[N][N], t4[N][N]; int lowbit(int x) { return x & (-x); } int n, m; void update(…

Mybatis实现RBAC权限模型查询

RBAC权限模型 Role-Based Access Control&#xff0c;中文意思是&#xff1a;基于角色&#xff08;Role&#xff09;的访问控制。这是一种广泛应用于计算机系统和网络安全领域的访问控制模型。 简单来说&#xff0c;就是通过将权限分配给➡角色&#xff0c;再将角色分配给➡用…

应急响应-网站入侵篡改指南Webshell内存马查杀漏洞排查时间分析

查看146天的内存马 方法&#xff1a; 1. 日志 这种地址一般在扫描 还要注意post传参注入 对其进行全局定位 发现有sql注入 我们可以也尝试去sqlmap注入 如果以这种方式注入ua头就会改变 2. 了解自己的中间件&#xff0c;框架&#xff0c;cve&#xff0c;等 因为不知道时间…

Unity中TimeLine的一些用法

Unity中TimeLine的一些用法 概念其他 概念 无Track模式&#xff08;PlayableAsset、PlayableBehaviour&#xff09; 1. 两者关系 运行在PlayableTrack中作用 PlayableBehaviour 实际执行的脚本字段并不会显示在timeline面板上 PlayableAsset PlayableBehaviour的包装器&#x…

[AI Perplexica] 安装指南:轻松部署AI驱动的开源搜索引擎

[AI Perplexica] AI驱动的开源搜索引擎[AI Perplexica] 深入解析&#xff0c;AI 架构揭秘 之前&#xff0c;我们看过了 Perplexica 的介绍&#xff0c;特点和架构&#xff0c;了解了其工作原理。 今天&#xff0c;我们一起来部署下 安装 docker 安装 docker https://docs.…

设计模式探索:代理模式

1. 什么是代理模式 定义 代理模式是一种结构型设计模式&#xff0c;通过为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和实际对象之间起到中介作用&#xff0c;可以在不改变真实对象的情况下增强或控制对真实对象的访问。 目的 代理模式的主要目的是隐…

【IT领域新生必看】Java编程中的神奇对比:深入理解`equals`与`==`的区别

文章目录 引言什么是操作符&#xff1f;基本数据类型的比较示例&#xff1a; 引用类型的比较示例&#xff1a; 什么是equals方法&#xff1f;equals方法的默认实现示例&#xff1a; 重写equals方法示例&#xff1a; equals与的区别比较内容不同示例&#xff1a; 使用场景不同示…

伯克利、斯坦福和CMU面向具身智能端到端操作联合发布开源通用机器人Policy,可支持多种机器人执行多种任务

不同于LLM或者MLLM那样用于上百亿甚至上千亿参数量的大模型&#xff0c;具身智能端到端大模型并不追求参数规模上的大&#xff0c;而是指其能吸收大量的数据&#xff0c;执行多种任务&#xff0c;并能具备一定的泛化能力&#xff0c;如笔者前博客里的RT1。目前该领域一个前沿工…

linux19:程序替换

一&#xff1a;最简单的看看程序替换是什么样的&#xff08;单个进程版&#xff09; 1 #include<stdio.h>2 #include<unistd.h>3 #include<stdlib.h>4 int main()5 {6 printf("Before : I am a process , myPid:%d,myPPid:%d\n",getpid(),getpp…

Java项目:基于SSM框架实现的德云社票务管理系统【ssm+B/S架构+源码+数据库+开题报告+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的德云社票务管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、功…

windows下搭建python+jupyter notebook

一.下载python 下面网址下载python3 https://www.python.org/ 二. 安装jupyter notebook 三. 修改配置 四. 检测是否正常运行

华为OD机试 - 跳马 - 广度优先搜索BFS(Java 2024 D卷 200分)

华为OD机试 2024D卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;D卷C卷A卷B卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测…

windows 7 安装IPP协议,支持Internet打印

1 windows 7 安装IPP协议,支持Internet打印 #控制面板--打开或关闭Windows功能 3 复制Printers 文件夹 到 c:\inetpub\wwwroot\,复制msw3prt.dll到c:\windows\system32\ 4 打开IIs管理器 #报错:模块列表中不存在此处理程序所需的指定模块。如果您添加脚本映射处理程序映射&…

Golang | Leetcode Golang题解之第218题天际线问题

题目&#xff1a; 题解&#xff1a; type pair struct{ right, height int } type hp []pairfunc (h hp) Len() int { return len(h) } func (h hp) Less(i, j int) bool { return h[i].height > h[j].height } func (h hp) Swap(i, j int) { h[i], h[j]…

独立开发者系列(20)——扫码登录

&#xff08;1&#xff09;网页端的安全登录设计 很多大型网站都有登录限制。这里以一个案例作为例子完整解析。理解安全的登录设计方式&#xff0c;无论对于以后做自动化&#xff0c;自动登录网站&#xff0c;获取数据&#xff0c;还是自己开发月租类型的系统非常有用。当前一…

从草图到现实:SketchUp 在建筑项目中的独特优势

Sketchup 是全球最受欢迎的建筑可视化平台之一。借助该平台提供的各种工具&#xff0c;您可以创建可供市场使用的逼真项目。Sketchup为什么如此优秀&#xff1f;它对建筑项目有哪些优势&#xff1f;下面&#xff0c;你将看到什么是 Sketchup 以及这个工具的一些重要的优势。 关…

新手如何尽快入门性能测试?

一、学习基础知识 性能测试的基本概念&#xff1a; 性能测试的定义&#xff1a;使用自动化工具&#xff0c;模拟不同的场景&#xff0c;对软件各项性能指标进行测试和评估的过程。 性能测试的目的&#xff1a;评估当前系统的能力、寻找性能瓶颈以优化性能、评估软件是否能够满…

高阶算法班从入门到精通之路课程

本课程旨在帮助学员深入理解算法与数据结构的核心概念&#xff0c;从而掌握高级算法设计与分析技能。每集课程内容精心设计&#xff0c;涵盖了常用数据结构、经典算法及其应用场景等方面的深度讲解&#xff0c;同时通过大量实例演练&#xff0c;帮助学员提升解决实际编程难题的…

【Dell R730 折腾记录】风扇调速--在 Ubuntu 系统上开机自启动并每隔30分钟执行一次风扇定速脚本

前段时间升级了一下机柜里的服务器&#xff0c;替换掉了一台旧的 Dell 服务器&#xff0c;换上了这台 R730。但是无奈于噪音的袭扰&#xff0c;搁置了一段时间。我在这台机器上目前安装了一块 Intel Xeon E5-2630v3 芯片以及一张改过散热的 NVIDIA Tesla P4 计算卡。结果就是散…

使用工业自动化的功能块实现大语言模型应用

大语言模型无所不能&#xff1f; 以chatGPT为代表的大语言模型横空出世&#xff0c;在世界范围内掀起了一场AI革命。给人的感觉似乎大模型语言无所不能。它不仅能够生成文章&#xff0c;图片和视频&#xff0c;能够翻译文章&#xff0c;分析科学和医疗数据&#xff0c;甚至可以…