探索C语言中的联合体和枚举:让处理数据更加得心应手

✨✨小新课堂开课了,欢迎欢迎~✨✨

🎈🎈养成好习惯,先赞后看哦~🎈🎈

所属专栏:http://t.csdnimg.cn/Oytke

小新的主页:编程版小新-CSDN博客

C语言中有内置类型, 比如:int ,char,short ,double,float等,但是仅用这些是不方便使用的,此次有了自定义类型,给了程序员更大的权力,以更好的追求性能。联合体能够将不同的类型聚在一起,放在一个共同的空间里,仿佛一损俱损,一荣俱荣。而枚举类型的使用仿佛更加的贴近生活,比如表述一个星期有七天,一年有12个月等。用枚举来写,增加代码的可读性和可维护性。

一:联合体类型 

1.联合体的定义

像结构体⼀样,联合体也是由一个或者多个成员构成,这些成员可以是不同的类型。但是编译器只为最大的成员分配足够的内存空间。

联合体的特点是所有成员共用同一块内存空间。所以联合体也叫:共用体

给联合体其中⼀个成员赋值,其他成员的值也跟着变化。

2.联合体的声明

union un   //   联合体关键字union+tag 标签
{
    int i;
    char c;     //  variable-name 联合体成员
    float f;
} a,b,c;   //  variable-list 变量列表

(1) 普通联合体

union un
{int i;char c;float f;
};

(2)嵌套联合体

//嵌套联合体
union u1
{int arr[4];float f;
};union un
{int i;char c;union u1 u;
};

 (3)匿名联合体

//匿名联合体
union
{char s;int b;float f;
};

小新:匿名联合体是一种比较特殊的联合体,匿名联合体顾名思义就是省略了它的名字,也就是所谓的tag-标签。匿名联合体只能使用一次,下次再要使用的时候,它已经不在了,这点要注意。

(4)typedef重命名的联合体

//typedef重命名的联合体
typedef union un
{int i;char str[4];
};

 3.联合体变量的创建和初始化

//联合体变量的创建和初始化
union un
{int i;char c;
};int main()
{//union un u = { 4,'s' };  //与结构体不同,这样初始化是错误的union un u = { 0 };//因为结构体成员公用一块内存区域,使用在初始化的时候只能初始化一个值return 0;
}

4.联合体的访问

联合体可以通过成员访问运算符(.)来访问其成员。与结构体相同,可以使用联合体变量和指向联合体的指针来访问成员。

#include<stdio.h>
#include<string.h>
union un
{int i;char c[10];
};int main()
{union un u = { 0 };printf("%d ", u.i);strcpy(u.c, "xiaoxin");printf("%s ",u.c );return 0;
}

运行结果:

5.联合体的特点 

联合的成员是共用同⼀块内存空间的,这样⼀个联合变量的大小,至少是最大成员的大小(因为联合 至少得有能力保存最大的那个成员)。

#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);return 0;
}

运行结果:

用画图的方式来解释就是这样的。

 

6.联合体大小的计算 

联合体在计算大小的时候和结构体一样,遵循着某种规则。

什么规则呢,如下:

• 联合的大小至少是最大成员的大小。

• 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

 示例1:

#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;
}

运行结果:

VS默认的最大对齐数是8,Un1的最大成员的大小是5,不是最大对齐数的整数倍,最终改为8;

Un2的最大成员的大小是14,不是最大对齐数的整数倍,最终改为16。 

7.联合体的应用

使用联合体是可以节省空间的,举例:

比如,我们要搞⼀个活动,要上线⼀个礼品兑换单,礼品兑换单中有三种商品:图书、杯⼦、衬衫。 每⼀种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。

图书:书名、作者、页数

杯子:设计

衬衫:设计、可选颜⾊、可选尺⼨

那我们不耐心思考,直接写出⼀下结构:

struct gift_list
{//公共属性 int stock_number;//库存量 double price; //定价 int item_type;//商品类型 //特殊属性 char title[20];//书名 char author[20];//作者 int num_pages;//⻚数 char 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 //匿名结构体{char design[30];//设计 }mug;struct //匿名结构体{char design[30];//设计 int colors;//颜⾊ int sizes;//尺⼨ }shirt;}item;};

8.用联合体判断大小端

int check_sys()
{union{int i;char c;}un;un.i = 1;//00  00  00  01return un.c;//返回1是⼩端,返回0是⼤端 
}

二:枚举类型 

1.枚举类型的定义

枚举是一种特殊的数据类型,用于定义一组有限的命名常量,这些命名常量又被称为枚举常量,它提供了一种简洁,可读性更高的方式来表示这些常量,并且通常具有类型安全性和可扩展性。

在实际应用中我们经常把能够且便于一一列举的类型用枚举来表示。

2.枚举的声明

enum  枚举类型名

{

   标识符1,

   标识符2,

   ...

};

 (1) 普通枚举

enum un
{MON=1, //指定从1开始,否则默认从0开始TUE,WED,THU, FRI, SAT, SUN
};

(2)匿名枚举

 //匿名枚举
enum
{MON = 1, //指定从1开始,否则默认从0开始TUE,WED,THU,FRI,  SAT,SUN
};

(3)typedef重命名的枚举

 typedef enum day
{MON = 1, //指定从1开始,否则默认从0开始TUE,WED,THU,FRI,SAT,SUN
};

3.枚举的特点

小新:我们用一些例子来说明它的特点吧

#iclude<stdio.h>
enum un
{MON, TUE,WED,THU,FRI,SAT,SUN
};int main()
{for (int i = MON; i <= SUN; i++){printf("%d ", i);}return 0;
}

运行结果:

{ }中的内容是枚举类型的可能取值,也叫枚举常量 。这些可能取值都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值

有请下一个例子登场

#include<stdio.h>
enum un
{red = 2,green,yellow,pink = 7,black,blue
};int main()
{printf("red = %d ",red);printf("green = %d ", green);printf("yellow = %d ", yellow);printf("pink = %d ", pink);printf("black= %d ", black);printf("blue = %d ", blue);return 0;
}

运行结果:

也可以通过这种赋值的方式改变取值

4.枚举常量的创建和初始化 

我们通常是用枚举常量来给枚举变量赋值的,在C语言中也可以用整数给枚举变量赋值,但是在C++中不能,C++要求的更加严格一些。

#include<stdio.h>
typedef enum un
{MON, TUE,WED,THU,FRI,SAT,SUM
}un;int main()
{un u = MON;//最好用枚举常量进行赋值return 0;
}

5.枚举类型的大小

枚举类型的大小和int的大小相等,都是4个字节,不信的话,小新就来证明一下。

#include<stdio.h>
enum day
{MON, TUE,WED,THU,FRI,SAT,SUN
};enum color
{red,blue,yellow,green
};int main()
{printf("%zd\n", sizeof(enum day));printf("%zd\n", sizeof(enum color));return 0;
}

运行结果:

6.枚举类型的优点 

为什么使用枚举? 我们可以使用 #define 定义常量,为什么非要使用枚举?

枚举的优点:

1. 增加代码的可读性和可维护性

2. 和#define定义的标识符比较,枚举有类型检查,更加严谨。

3. 便于调试,预处理阶段会删除 #define 定义的符号

4. 使用方便,⼀次可以定义多个常量

5. 枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用

7.枚举的应用

计算器的实现有多种方法,今天我们用枚举来实现计算器

运行结果:


下课了下课了~

下次还要来上课哦~ 

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

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

相关文章

2024年云计算使用报告,89%组织用多云,25%广泛使用生成式AI,45%需要跨云数据集成,节省成本是云首要因素

备注&#xff1a;本文来自Flexera2024年的云现状调研报告的翻译。原报告地址&#xff1a; https://info.flexera.com/CM-REPORT-State-of-the-Cloud Flexera是一家专注于做SaaS的IT解决方案公司&#xff0c;有30年发展历史&#xff0c;5万名客户&#xff0c;1300名员工。Flex…

​数据结构—栈操作经典案例

括号匹配&#xff1a; 这是我最开始写的&#xff0c;运行有问题 对于输入的括号序列&#xff0c;建议使用标准的 C 字符串而不是字符数组。 #include<iostream> using namespace std;typedef char SelemType; typedef int Status; #define OK 1 #define MAXSIZE 100 #…

python基础——异常捕获【try-except、else、finally】

&#x1f4dd;前言&#xff1a; 这篇文章主要介绍一下python基础中的异常处理&#xff1a; 1&#xff0c;异常 2&#xff0c;异常的捕获 3&#xff0c;finally语句 &#x1f3ac;个人简介&#xff1a;努力学习ing &#x1f4cb;个人专栏&#xff1a;C语言入门基础以及python入门…

【C++】右值引用

目录 前言&#xff1a;一、左值引用和右值引用1.1 什么是左值和左值引用1.2 什么是右值和右值引用 二、左值引用和右值引用比较三、右值引用使用场景3.1 传值返回使用场景3.2 移动构造3.3 移动赋值3.4 STL容器接口也增加右值引用3.5 完美转发 前言&#xff1a; 引用是给对象取…

HarmonyOS 应用开发之模型切换

本文介绍如何将一个FA模型开发的声明式范式应用切换到Stage模型&#xff0c;您需要完成如下动作&#xff1a; 工程切换&#xff1a;新建一个Stage模型的应用工程。 配置文件切换&#xff1a;config.json切换为app.json5和module.json5。 组件切换&#xff1a;PageAbility/Serv…

不同的batch_size对精度和损失的影响研究

1 问题 不同的batch_size对训练集和验证集的精度和损失的影响有多大&#xff1f; 2 方法 通过设置不同batch_size算出不同batch_size对应的训练集精度、训练集损失和验证集的精度和损失&#xff0c;通过数据可视化将精度和损失展示出来&#xff0c;比较出不同batch_size对他们的…

CTK插件框架学习-插件注册调用(03)

CTK插件框架学习-新建插件(02)https://mp.csdn.net/mp_blog/creation/editor/136923735 一、CTK插件组成 接口类&#xff1a;对外暴露的接口&#xff0c;供其他插件调用实现类&#xff1a;实现接口内的方法激活类&#xff1a;负责将插件注册到CTK框架中 二、接口、插件、服务…

文生视频大模型Sora的复现经验

大家好&#xff0c;我是herosunly。985院校硕士毕业&#xff0c;现担任算法研究员一职&#xff0c;热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名&#xff0c;CCF比赛第二名&#xff0c;科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的…

BFS专题

1、BFS解决FloodFill算法 1、1图像渲染 733. 图像渲染 - 力扣(LeetCode) class Solution {typedef pair<int,int> PII;int dx[4] = {0,0,1,-1};int dy[4] = {1,-1,0,0}; public:vector<vector<int>> floodFill(vector<vector<int>>& i…

RIP环境下的MGRE 综合实验

实验题目及要求&#xff1a; 1.R5为ISP&#xff0c;只能进行IP地址配置&#xff0c;其所有地址均配为公有IP地址 2.R1和R5间使用PPP的PAP认证&#xff0c;R5为主认证方; R2于R5之间使用PPP的chap认证&#xff0c;R5为主认证方&#xff1b; R3于R5之间使用HDLC封装。 3.R1/…

【C++】为什么能实现函数重载

从C语言一路学到C的途中&#xff0c;C语言C语言相比&#xff0c;多了个函数重载&#xff0c;那么函数重载是如何实现的呢&#xff0c;为什么C语言无法支持&#xff0c;在本篇博客中&#xff0c;将会讲解C为何能实现函数重载。 一.编译过程 C能实现函数重载&#xff0c;而C语言不…

QT 二维坐标系显示坐标点及点与点的连线-通过定时器自动添加随机数据点

QT 二维坐标系显示坐标点及点与点的连线-通过定时器自动添加随机数据点 功能介绍头文件C文件运行过程 功能介绍 上面的代码实现了一个简单的 Qt 应用程序&#xff0c;其功能包括&#xff1a; 创建一个 MainWindow 类&#xff0c;继承自 QMainWindow&#xff0c;作为应用程序的…

2024软件设计师备考讲义——UML(统一建模语言)

UML的概念 用例图的概念 包含 <<include>>扩展<<exted>>泛化 用例图&#xff08;也可称用例建模&#xff09;描述的是外部执行者&#xff08;Actor&#xff09;所理解的系统功能。用例图用于需求分析阶段&#xff0c;它的建立是系统开发者和用户反复…

Pyppeteer中Chromium安装步骤

1、下载压缩文件 在官网下载chrome-win.zip文件 2、终端下载pyppeteer 首先在Pycharm终端运行pip install pyppeteer 3、查找文件默认路径 在运行以下代码&#xff0c;找到可执行文件默认路径 import pyppeteer.chromium_downloader print(默认版本是&#xff1a;{}.forma…

牛角工具箱源码 轻松打造个性化在线工具箱

&#x1f389; Whats this&#xff1f; 这是一款在线工具箱程序&#xff0c;您可以通过安装扩展增强她的功能 通过插件模板的功能&#xff0c;您也可以把她当做网页导航来使用~ 觉得该项目不错的可以给个Star~ &#x1f63a; 演示地址 https://tool.aoaostar.com &#x1f…

TCP网络协议栈和Posix网络部分API总结

文章目录 Posix网络部分API综述TCP协议栈通信过程TCP三次握手和四次挥手&#xff08;看下图&#xff09;三次握手常见问题&#xff1f;为什么是三次握手而不是两次&#xff1f;三次握手和哪些函数有关&#xff1f;TCP的生命周期是从什么时候开始的&#xff1f; 四次挥手通信状态…

HarmonyOS实战开发-如何实现一个自定义抽奖圆形转盘

介绍 本篇Codelab是基于画布组件、显式动画&#xff0c;实现的一个自定义抽奖圆形转盘。包含如下功能&#xff1a; 通过画布组件Canvas&#xff0c;画出抽奖圆形转盘。通过显式动画启动抽奖功能。通过自定义弹窗弹出抽中的奖品。 相关概念 Stack组件&#xff1a;堆叠容器&am…

从0开始搭建基于VUE的前端项目(一) 项目创建和配置

准备与版本 安装nodejs(v20.11.1)安装vue脚手架(@vue/cli 5.0.8) ,参考(https://cli.vuejs.org/zh/)vue版本(2.7.16),vue2的最后一个版本vue.config.js的配置详解(https://cli.vuejs.org/zh/config/)element-ui(2.15.14)(https://element.eleme.io/)vuex(3.6.2) (https://…

K8S命令行可视化实验

以下为K8s命令行可视化工具的实验内容&#xff0c;相比于直接使用命令行&#xff0c;可视化工具可能更直观、更易于操作。 Lens Lens是用于监控和调试的K8S IDE。可以在Windows、Linux以及Mac桌面上完美运行。在 Kubernetes 上&#xff1a; 托管地址&#xff1a;github/lensa…

机器人运动控制

一、基础 1.1 矢量速度和旋转速度 矢量速度用来控制运动方向&#xff0c;任何一个方向都可以看成x、y、z三轴方向的合。单位规定是m/s。 旋转速度用来控制旋转方向&#xff0c;可以看成x、y、z三轴方向旋转的合。单位规定是pi/s。 速度消息包&#xff0c;可以在ROS Index上搜…