联合体类型和枚举类型

联合体 

联合体类型的声明

像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。 
联合体的特点是所有成员共⽤同⼀块内存空间。所以联合体也叫:共⽤体。
所以给联合体其中⼀个成员赋值,其他成员的值也跟着变化。

对于联合体,其语法结构和结构体对比可以说唯一的变换就是把struct换成union,其他的都一模一样,所以我们知道了struct的语法结构相当于知道union的语法结构,其初始化和创建也就得心应手。(上篇文章已经讲了struct的语法结构(声明),这里就不讲了,不知道的可以翻到上篇文章看一下)

并且之前也讲过,对于union也可以进行匿名操作,间接访问操作符和直接访问操作符也可以应用在上面。

对于我们上一篇的位段同理上述行为也可以,并且位段和前面两种类型的语法结构也很相似,就是多了个:和数字,关键字还是struct。

所以这三种类型的语法结构可以说都非常相似,但是其内部成员的内存分配可完全不一样。结构体和位段的内存分配我已经讲过了,下面带来联合体的内存分配

#include <stdio.h>
//联合类型的声明
union Un
{
char c;
int i;
};
int main()
{
//联合变量的定义
union Un un = {0};
//计算连个变量的⼤⼩
printf("%d\n", sizeof(un));
return 0;}

 为什么为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;
}

数组的对齐数是默认对齐数和其成员类型大小的较小值,像char c[5]对齐数为1.所以分析得出结果为8,16.。验证得知正确。(说了以上结论后想必推导出结果很简单,就不说其结果的推导)

而其最大成员大小分别为 5和14,但是其联合体大小为 8 和16.

所以联合体大小至少是最大成员的大小,且当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候,就要对⻬到最⼤对⻬数的整数倍。

 对于联合体的各个成员都是从联合体的首个字节开始进行存储(像联合体这种包含多个数据的类型内部都是从低地址到高地址进行存储,数组,结构体这种包含多个数据的也是同理)。从而会共用同一块内存空间。

下面有一段代码去支持以上结论

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

 

足以说明每个成员都是从联合体的首个字节开始进行存储的,从而会有共用 。导致它们之间有关联,改变其中一个值,可能会导致其他值发生变化。

 所以这就是联合体的内存分配。

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

 我们再对⽐⼀下相同成员的结构体和联合体的内存布局情况

struct S
{char c;int i;
};
struct S s = {0};
union Un
{ 
char c;
int  i;
};
union Un un = {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;
};

 这样的代码所创造出的struct空间大小因为内含union的缘故,所以不通用的属性是共用一块内存,而之前的代码是不存在共用的,都是独立的。

所以优化后的版本在能达到同样的效果时且其空间更小,更节省内存。

用联合体的方式判断大小端存储模式 

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

 这里就不过多叙述了,很简单的一题,只要学过数据在内存中的存储的就都知道其具体机制。

枚举 

 枚举类型的声明

enum Day//星期
{Mon,Tues,Wed,Thur,Fri,Sat,Sun
};
enum Sex//性别
{MALE,FEMALE,SECRET
};
enum Color//颜⾊
{RED,GREEN,BLUE
};

枚举跟前面的结构体和联合体完全不同。差别很大。

以上定义的 enum Day enum Sex enum Color 都是枚举类型。

{}中的内容是枚举类型变量的可能取值,也叫枚举常量(注意这是常量) 。 这些可能取值都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值。(因为是常量,在赋完初值后不可再改变其值)

enum Color//颜⾊
{RED=2,GREEN=4,BLUE=8
};

注意{}里面的是,不是;    

枚举类型的使用 

enum Color//颜⾊
{RED=1,GREEN=2,BLUE=4
};
enum Color clr = GREEN;//使⽤枚举常量给枚举变量赋值

我们用sizeof对其测试得出一系列结论

一系列枚举类型如enum  color等等本质其实是int 类型 ,因为其类型大小为4个字节。

而对于枚举常量类型为enum color  ,其类型大小也为4个字节

所以对于创建的clr变量我们将其赋值是用枚举常量给其赋值。

不能用整数将其赋值,如4,5,6等。因为其是int类型,而这个是enum color类型。

而有些人在c语言中可以实现用4,5,6等整形将其赋值给枚举变量的情况,这是因为c语言不够严谨,而其枚举类型本质上其实还是int类型,所以就让它过了。 如果换做c++,其类型检查比较严格,所以即使其枚举类型本质是int类型,但其表面还是枚举类型,严格的c++就会导致不能用整形赋值到枚举变量上去。

所以对于枚举变量我们为了严谨性还是只能用枚举常量对其进行赋值(只能选对应的枚举类型{}里面的枚举常量)

当然对于枚举常量我们不仅能给枚举变量赋值,还能单拿出来自己用在别的地方 (它们是已经定义好的常量,当然能自己单独用)

枚举依然能进行匿名操作。枚举不能用直接访问操作符和间接访问操作符。枚举依然能像结构体和联合体一样在;前面创建变量(创建类型的同时创建变量) 

这大概就是枚举的主要知识点,当然它还有更多的细节,对于这些细节我就不讲了(实在有点多),这里有篇好文我推荐下,大家可以去看下C语言枚举类型enum(全面详细直观)_enum c语言-CSDN博客

讲的枚举知识点比我详细的多,(我这只是讲一下主要的知识点,没更深涉及了,你应用枚举基本上也就是应用到我这上面讲的知识点)

 枚举的优点

为什么使⽤枚举?
我们可以使⽤ #define 定义常量,为什么⾮要使⽤枚举?
枚举的优点:
1. 增加代码的可读性和可维护性
2. 和#define定义的标识符⽐较枚举有类型检查,更加严谨。
3. 便于调试,预处理阶段会删除 #define 定义的符号
4. 使⽤⽅便,⼀次可以定义多个常量
5. 枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使⽤。(也能声明在函数外,此时就能在全局使用)。而#define定义的常量都是在全局使用的,不会被限制到只能在函数内使用。

总结 

所以目前我们就讲解完了联合体和枚举  。 下一篇将给大家讲解动态内存管理。

谢谢大家!!!

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

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

相关文章

新手养布偶猫如何选择猫主食冻干?K9、sc、希喂三个品牌推荐!

布偶猫是食肉动物&#xff0c;但由于肠胃脆弱敏感&#xff0c;所以在饮食上需要特别关注哦&#xff01;为了给它们最好的呵护&#xff0c;现在有了主食冻干这种优质猫主食&#xff01;它不仅符合猫咪的天然饮食习惯&#xff0c;还用了新鲜生肉做原料呢&#xff01;营养满分不说…

腾讯云2核2G3M服务器可以运行几个网站?

在探讨这个问题之前&#xff0c;我们需要先了解网站运行所需的基本资源。一个网站的运行通常需要以下几个方面的资源&#xff1a;CPU、内存、磁盘和网络。接下来&#xff0c;我们将分析这些资源在不同配置下的使用情况&#xff0c;以确定腾讯云2核2G3M服务器可以运行多少个网站…

计算机毕业设计 SpringBoot的中小型制造企业质量管理系统 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

基于JavaWeb+SSM+Vue家政项目微信小程序系统的设计和实现

基于JavaWebSSMVue家政项目微信小程序系统的设计和实现 源码获取入口Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码获取入口 Lun文目录 目录 1系统概述 1 1.1 研究背景 1 1.2研究目的 1 1.3系统设计思想 1 2相关技术 2…

element-ui table height 属性导致界面卡死

问题: 项目上&#xff0c;有个点击按钮弹出抽屉的交互, 此时界面卡死 原因分析: 一些场景下(父组件使用动态单位/弹窗、抽屉中使用), element-ui 的 table 会循环计算高度值, 导致界面卡死 github 上的一些 issues 和解决方案: Issues ElemeFE/element GitHub 官方讲是升…

基于粒子群算法的曲面路径优化

目录 摘要 测试函数shubert 粒子群算法的原理 粒子群算法的主要参数 粒子群算法原理 粒子群算法参数拟合 代码 结果分析 展望 基于粒子群算法的曲面路径优化(代码完整,数据齐全)资源-CSDN文库 https://download.csdn.net/download/abc991835105/88698419 摘要 寻优算法,…

九州金榜|父母忙碌,更要高质量陪伴孩子

逐渐加快的生活节奏让每一个人都在马不停蹄的运转&#xff0c;愈加优越的生活条件也让人们对生活环境有更高的要求&#xff0c;这让很多家长在创造物质条件时却疏于对孩子的家庭教育。 这些家长也意识到了这种做法下的危害&#xff0c;但是却不愿为此改变&#xff0c;甚至在不忙…

JAVAEE初阶相关内容第二十弹--HTTP协议【续集】

写在前&#xff1a;在前一篇博客中我们初步掌握了HTTP(超文本传输协议)的相关知识【点击跳转】&#xff0c;认识了HYYP协议的工作过程&#xff0c;掌握抓包工具Fiddler的使用。在“方法”中重点需要理解“GET”方法与“POST”方法的格式与内容&#xff0c;并了解了请求“报头”…

C++:stack、queue、priority_queue增删查改模拟实现、deque底层原理

C:stack、queue、priority_queue增删查改模拟实现 前言一、Cstack的介绍和使用1.1 引言1.2 satck模拟实现 二、Cqueue的介绍和使用2.1 引言2.2 queue增删查改模拟实现 三、STL标准库中stack和queue的底层结构:deque3.1 deque的简单介绍(了解)3.2 deque的缺陷3.3 为什么选择dequ…

Spring Boot实现数据加密脱敏:注解 + 反射 + AOP

文章目录 1. 引言2. 数据加密和脱敏的需求3. Spring Boot项目初始化4. 敏感数据加密注解设计5. 实现加密和脱敏的工具类6. 实体类和加密脱敏注解的使用7. 利用AOP实现加密和脱敏8. 完善AOP切面9. 测试10. 拓展功能与未来展望10.1 加密算法的选择10.2 动态注解配置 11. 总结 &am…

IoTDB 集群部署——windows

本文的测试环境为window server2016&#xff0c;版本包为1.1.0&#xff0c;jdk版本为1.8 首先下载IoTDB版本包&#xff0c;链接地址如下 https://archive.apache.org/dist/iotdb/1.1.0/apache-iotdb-1.1.0-all-bin.zip 本次部署将使用1个ConfigNode 和3个DataNode模式&#…

Rancher 单节点 docker 部署备份与恢复

Rancher 单节点 docker 部署备份与恢复 1. 备份集群 获取 rancher server 容器名&#xff0c;本例为 angry_aryabhata docker ps | grep rancher/rancher6a27b8634c80 rancher/rancher:v2.5.14 xxx angry_aryabhata停止容器 docker stop angry_aryabhata创建备…

深入理解Vue3中的自定义指令

Vue3是一个流行的前端框架&#xff0c;它引入了许多新特性和改进&#xff0c;其中之一是自定义指令。自定义指令是一种强大的功能&#xff0c;可以让开发者在模板中直接操作 DOM 元素。本文将深入探讨 Vue3中的自定义指令&#xff0c;包括自定义指令的基本用法、生命周期钩子函…

uniappVue3版本中组件生命周期和页面生命周期的详细介绍

一、什么是生命周期&#xff1f; 生命周期有多重叫法&#xff0c;有叫生命周期函数的&#xff0c;也有叫生命周期钩子的&#xff0c;还有钩子函数的&#xff0c;其实都是代表&#xff0c;在 Vue 实例创建、更新和销毁的不同阶段触发的一组钩子函数&#xff0c;这些生命周期函数…

Flutter 混合开发 - aar打包

背景 项目接入 Flutter 后有两种方式&#xff0c;一种是 module 引入开发&#xff0c;一种是 aar 依赖开发。当前项目中在 Debug 阶段为了方便调试采用 module 开发&#xff0c;在发版时&#xff08;即 Release 阶段&#xff09;采用 aar 依赖引入。为了配合这种模式就需要在 …

个人笔记:分布式大数据技术原理(一)Hadoop 框架

Apache Hadoop 软件库是一个框架&#xff0c;它允许使用简单的编程模型&#xff0c;实现跨计算机集群的大型数据集的分布式处理。它最初的设计目的是为了检测和处理应用程序层的故障&#xff0c;从单个机器扩展到数千台机器&#xff08;这些机器可以是廉价的&#xff09;&#…

学会视频剪辑方法:从视频中提取封面,增加视频观看量

在数字媒体时代&#xff0c;视频已经成为信息传递的主要方式之一。那如何让视频在众多内容中脱颖而出&#xff0c;吸引更多的观众呢&#xff1f;除了内容本身的质量外&#xff0c;视频的封面也是吸引的关键因素之一。下面一起看云炫AI智剪如何通过视频剪辑方法从视频中提取封面…

Vue框架底层

一、前端框架的由来 1、服务端渲染 sequenceDiagram 浏览器->>服务器: https://www.bilibili.com/ Note right of 服务器: 组装页面(服务端渲染) 服务器->>-浏览器: 完整页面2、前后端分离 sequenceDiagram 浏览器->>服务器: https://www.bilibili.com/ 服务…

2023 年中国高校大数据挑战赛赛题B DNA 存储中的序列聚类与比对-解析与参考代码

题目背景&#xff1a;目前往往需要对测序后的序列进行聚类与比对。其中聚类指的是将测序序列聚类以判断原始序列有多少条&#xff0c;聚类后相同类的序列定义为一个簇。比对则是指在聚类基础上对一个簇内的序列进行比对进而输出一条最有 可能的正确序列。通过聚类与比对将会极大…

Vue页面传值:Props属性与$emit事件的应用介绍

一、vue页面传值 在Vue页面中传值有多种方式&#xff0c;简单介绍以下两种 通过props属性传递值&#xff1a;父组件在子组件上定义props属性&#xff0c;子组件通过props接收父组件传递的值。通过$emit触发事件传递值&#xff1a;子组件通过$emit方法触发一个自定义事件&#…