C语言第三十二弹---自定义类型:联合和枚举

news/2024/4/16 2:42:01

个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】

目录

1、联合体

1.1、联合体类型的声明

1.2、联合体的特点

1.3、相同成员的结构体和联合体对比

1.4、联合体大小的计算

1.5、联合的⼀个练习

2、枚举类型

2.1、枚举类型的声明

2.2、枚举类型的优点

2.3、枚举类型的使用

总结


1、联合体

1.1、联合体类型的声明

像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。
但是编译器 只为最大的成员分配足够的内存空间 。联合体的特点是 所有成员共用同⼀块内存空间。 所以联合体也叫: 共用体
给联合体其中⼀个成员赋值,其他成员的值也跟着变化。
#include <stdio.h>
//联合类型的声明
union Un
{char c;int i;
};int main()
{//联合体局部变量的定义union Un un = {0};//计算联合体变量的大小printf("%d\n", sizeof(un));return 0;
}
那现在uu来思考一个问题,上面的联合体变量un的大小是多少?
输出的结果:
为什么是4呢?
计算联合体的大小跟结构体类似,需要知道联合体的内存布局,才能准确计算出大小,因此我们先学习关于联合体的相关知识再来详细讲解计算大小问题。

1.2、联合体的特点

联合的成员是共⽤同⼀块内存空间的,这样⼀个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。
//代码1
#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;
}
通过上述代码我们可以知道联合体的每个成员地址和联合体的首地址是相同的。
//代码2
#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;
}
输出的结果:
代码1输出的三个地址⼀模⼀样,代码2的输出,我们发现将i的第4个字节的内容修改为55了。
我们仔细分析就可以画出,un的内存布局图。

1.3、相同成员的结构体和联合体对比

我们再对比⼀下相同成员的结构体和联合体的内存布局情况。
struct S
{char c;int i;
};
struct S s = {0};
union Un
{char c;int i;
};
union Un un = {0};

1.4、联合体大小的计算

联合的大小至少是最大成员的大小。
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
注意:对齐数跟结构体说描述的对齐数是相同的。
#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;
}
使用联合体是可以节省空间的,举例:
比如,我们要搞⼀个活动,要上线⼀个礼品兑换单,礼品兑换单中有三种商品:图书、杯⼦、衬衫。
每⼀种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。
图书:书名、作者、页数
杯⼦:设计
衬衫:设计、可选颜色、可选尺寸
那我们不耐心思考,直接写出⼀下结构:
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;
};

1.5、联合的⼀个练习

写⼀个程序,判断当前机器是大端?还是小端?
int check_sys()
{union//匿名联合体{int i;char c;}un;//联合体变量un.i = 1;//16进制为00 00 00 01   内存中存储为01 00 00 00  (小端)//下图表示的是内存中的存储return un.c;//返回1是⼩端,返回0是⼤端
}

注:联合体的定义初始化以及匿名联合体和结构体方式一致,此处就不详细讲解了。可以去看上两弹的结构体创建定义初始化以及匿名结构体。

2、枚举类型

2.1、枚举类型的声明

枚举顾名思义就是⼀⼀列举。
把可能的取值⼀⼀列举。
比如我们现实生活中:
⼀周的星期⼀到星期日是有限的7天,可以⼀⼀列举
性别有:男、女、保密,也可以⼀⼀列举
月份有12个月,也可以⼀⼀列举
三原色,也是可以意义列举
这些数据的表示就可以使用枚举了。
enum Day//星期
{Mon,//0Tues,//1Wed,//2Thur,Fri,Sat,Sun
};
enum Sex//性别
{MALE,//0FEMALE,//1SECRET//2
};
enum Color//颜⾊
{RED,//0GREEN,//1BLUE//2
};
以上定义的 enum Day enum Sex enum Color 都是枚举类型。
{}中的内容是枚举类型的可能取值,也叫 枚举常量
这些可能取值都是有值的, 默认从0开始,依次递增1 ,当然在声明枚举类型的时候也可以赋初值。
enum Color//颜⾊
{RED=2,GREEN=4,BLUE=8
};

2.2、枚举类型的优点

为什么使用枚举?
我们可以使用  #define 定义常量,为什么用要使用枚举?
枚举的优点:
1. 增加代码的可读性和可维护性。
2. 和#define定义的标识符比较枚举有类型检查,更加严谨。
3. 便于调试,预处理阶段会删除 #define 定义的符号。
4. 使用方便,⼀次可以定义多个常量。
5. 枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用。

2.3、枚举类型的使用

enum Color//颜⾊
{RED=1,GREEN=2,BLUE=4
};
enum Color clr = GREEN;//使⽤枚举常量给枚举变量赋值
那是否可以拿整数给枚举变量赋值呢?在C语言中是可以的,但是在C++是不行的,C++的类型检查比较严格。

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!


http://www.ppmy.cn/news/1365078.html

相关文章

关于CSS常见选择器应用的基础教程

在网页开发中&#xff0c;CSS选择器是非常重要的一部分&#xff0c;它们用来指定你想要样式化的HTML元素。熟练掌握各种选择器的用法可以帮助你更有效地实现网页布局和设计。本文将介绍一些常见的CSS选择器&#xff0c;并演示它们的基本用法及应用场景。 一、元素选择器&#…

Android 接入指纹识别

接入指纹框架&#xff1a;https://github.com/Tencent/soter implementation com.github.Tencent.soter:soter-wrapper:2.0.91.Application中初始化 class IApplication : Application() {override fun onCreate() {super.onCreate()instance thisinitSort()}private fun in…

数仓项目6.0(二)数仓

中间的几步意义就在于&#xff0c;缓存中间处理数据样式&#xff0c;避免重复计算浪费算力 分层 ODS&#xff08;Operate Data Store&#xff09; Spark计算过程中&#xff0c;存在shuffle的操作&#xff0c;而shuffle会将计算过程一分为二&#xff0c;前一阶段不执行完&…

我的NPI项目之设备系统启动(八) -- Android14的GKI2.0开发步骤和注意事项

GKI是什么&#xff1f; Google为什么要推行GKI&#xff1f; GKI全称General Kernel Image。GKI在framework和kernel之间提供了标准接口&#xff0c;使得android OS能够轻松适配/维护/兼容不同的设备和linux kernel。 Google引入GKI的目的是将Framework和Kernel进一步的解耦。因…

IBM在闪存系统集成实时恶意软件I/O检测功能

IBM在其最新一代FlashCore Modules&#xff08;FCMs&#xff09;固件中集成了使用机器学习进行实时勒索软件和其他攻击检测的功能。这些FCMs是专用于IBM FlashSystem 5000和Storwize阵列的闪存驱动器&#xff0c;采用U.2外形尺寸及NVMe接口。现有的第三代FCMs分别提供4.8、9.6、…

连接未来:嵌入式系统在物联网时代的应用

连接未来&#xff1a;嵌入式系统在物联网时代的应用 随着物联网技术的不断发展&#xff0c;嵌入式系统在物联网时代扮演着至关重要的角色。嵌入式系统作为连接物理世界和数字世界的桥梁&#xff0c;为物联网的实现提供了技术支持和基础设施。以下将从几个方面探讨嵌入式系统在…

Rocky Linux 运维工具 Systemd

一、Systemd 的简介 Systemd是一个用于管理Linux系统启动进程和服务的系统和服务管理器&#xff0c;取代了传统的init系统。它提供了并行启动、依赖关系管理、动态加载服务文件等功能&#xff0c;成为现代Linux发行版中主流的初始化系统。 二、Systemd 的参数说明 [Unit] Des…

Linux设备模型(二) - kset/kobj/ktype APIs

一&#xff0c;kobject_init_and_add 1&#xff0c;kobject_init_and_add实现 /** * kobject_init_and_add() - Initialize a kobject structure and add it to * the kobject hierarchy. * kobj: pointer to the kobject to initialize * ktype: p…

来分析两道小题

一、源码 二、分析 首先它会接两个参数一个是id一个是ps&#xff0c;传递的话会包含一个flag.php&#xff0c;然后数据库连接&#xff0c;之后传递过滤&#xff0c;然后查询&#xff0c;如果查到了就会取id&#xff0c;取出来看是不是跟adog一样&#xff0c;如果是它告诉你账号…

备战蓝桥杯————k个一组反转单链表

k个反转单链表&#xff0c;顾名思义就是k个节点为一组进行反转&#xff0c;这是一道困难的题目&#xff0c;如何解答&#xff0c;可以在我们前面的反转链表中得到思路。 如何 K 个一组反转单链表 题目描述 给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xf…

React引入css的几种方式以及应用

1.直接引入css文件 import "./parent.css" 2.引入css模块&#xff0c;定义文件名[组件名.module.css]&#xff1b;该方式可避免类名的重复&#xff0c;每个组件都有独立的作用域&#xff0c;避免了全局污染&#xff0c;保证了类名的唯一性 import styles from &qu…

300分钟吃透分布式缓存-15讲:如何深入理解、应用及扩展 Twemproxy?

Twemproxy 架构及应用 Twemproxy 是 Twitter 的一个开源架构&#xff0c;它是一个分片资源访问的代理组件。如下图所示&#xff0c;它可以封装资源池的分布及 hash 规则&#xff0c;解决后端部分节点异常后的探测和重连问题&#xff0c;让 client 访问尽可能简单&#xff0c;同…

vue3编写H5适配横竖屏

具体思路如下&#xff1a; 1、监听浏览器屏幕变化&#xff0c;通过监听屏幕宽高&#xff0c;辨别出是横屏&#xff0c;还是竖屏状态 在项目的起始根页面进行监听&#xff0c;我就是在App.vue文件下进行监听 代码如下&#xff1a; <template><RouterView /> <…

Mycat核心教程--Mycat 监控工具【四】

Mycat核心教程--Mycat 监控工具 九、Mycat 监控工具9.1.Mycat-web 简介9.2.Mycat-web 配置使用9.2.1.ZooKeeper 安装【上面有】9.2.2.Mycat-web 安装9.2.2.1.下载安装包9.2.2.2.安装包拷贝到Linux系统/opt目录下&#xff0c;并解压9.2.2.3.拷贝mycat-web文件夹到/usr/local目录…

LVS负载均衡服务器

简介: LVS (Linux Virtual Server):四层路由设备&#xff0c;是由中国人章文松研发的(阿里巴巴的副总裁)根据用户请求的IP与端口号实现将用户的请求分发至不同的主机。 工作原理: LVS工作在一台server上提供Directory(负载均衡器)的功能&#xff0c;本身并不提供服务&#xff…

s-table和columns初始化不完整,造成table文件的filter报错

问题 顺藤摸瓜找errorHandler.js文件 发现文件并没有什么问题 顺藤摸瓜找index.vue文件 首先找到报错的filter&#xff0c;发现与columnsSetting相关 找到columnsSetting发现等于columns 返回自己使用S-table组件的地方&#xff0c;发现columns初始化时仅初始化为ref()未表明…

【web】云导航项目部署及环境搭建(复杂)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、项目介绍1.1项目环境架构LNMP1.2项目代码说明 二、项目环境搭建2.1 Nginx安装2.2 php安装2.3 nginx配置和php配置2.3.1 修改nginx文件2.3.2 修改vim /etc/p…

状态模式(State Pattern)

定义 状态模式&#xff08;State Pattern&#xff09;是一种行为设计模式&#xff0c;它允许对象在其内部状态改变时改变其行为。这意味着&#xff0c;当对象的状态发生变化时&#xff0c;它的行为也会发生变化。状态模式特别适用于行为依赖于其状态的对象&#xff0c;而且当这…

猫头虎分享已解决Bug || Error: Minified React error #130

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

【数据库】mybatis使用总结

文章目录 1. 批量插入、检索<foreach>2. <if> 判断等于情况3. 模糊查询(pgsql为例)4. 分页5. <resultMap > 中collection 和association 1. 批量插入、检索<foreach> <insert id"insertSystemService" >insert into SYSTEMINFO_SER…
最新文章