【C语言】——联合体与枚举

【C语言】——联合体与枚举

    • 一、联合体
      • 1.1、联合体类型的声明
      • 1.2、联合体的特点
      • 1.3、相同成员的结构体和联合体对比
      • 1.4、联合体的大小计算
      • 1.5、联合体的应用举例
    • 二、枚举
      • 2.1、枚举类型的声明
      • 2.2、枚举类型的优点

一、联合体

1.1、联合体类型的声明

  
  联合体也叫做共用体
  与结构体一样,联合体也是自定义类型,同样,也是由一个或多个的成员构成,这些成员类型可以相同也可以不同。
  与结构体不同的是,编译器只会为联合体中最大的成员开辟足够的内存空间。正如联合体这个名字一样,联合体的所有成员共用这一块内存空间
  这样,因为使用的是同一块内存,一个联合体成员改变,其他联合体成员也会跟着改变
  
  联合体的声明与结构体非常类似,下面我们直接看代码:

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

  
运行结果:

在这里插入图片描述

  为什么大小是 4 呢?我们一起来学习联合体的特点
  

1.2、联合体的特点

  联合体最大的特点就是所有成员共用一块内存空间,因此联合体变量的大小,至少最大成员变量的大小(因为联合体至少保证有能力存储那个成员)
  
  我们可以通过代码来理解联合体的特点
  
代码一:

#include<stdio.h>//联合类型的声明
union Un
{char c;int i;
};int main()
{//联合变量的定义union Un un = { 0 };//下面输出的结果是一样的吗?printf("%d\n", &(un.i));printf("%d\n", &(un.c));printf("%d\n", &un);
}

  
运行结果:
在这里插入图片描述

  
代码二:

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

运行结果:

在这里插入图片描述

  
  可以看到,代码一中,取出的三个地址都是一样的,说明成员之间共用一个内存空间
  
  至于代码二,我们发现低位字节的内容改了,我们可以通过画图来分析
  

在这里插入图片描述

  

  看到这里,不知大家有没有联想到判断大小端存储(详情请看【C语言】——数据在内存中的存储),是的,我们可以利用联合体来对判断机器是大端存储还是小端存储
  

int check_sys()
{union{int i;char c;}un;un.i = 1;return un.c;
}

  
  我们往联合体成员 i i i 中放入1,在返回联合体成员 c c c,因为 c c c c h a r char char 类型,取出的是 i i i地址最小的字节的内容,当取出值为 1,说明低位数字放低地址,为小端存储;如果为 0,说明低位数字放高地址,为大端存储
  
  

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

  
  下面,我们来对比一下相同成员的结构体和联合体的内存布局情况:

struct S
{char c;int i;
};union Un
{char c;int i;
};

  

在这里插入图片描述

  

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

  
运行结果:

在这里插入图片描述

  

为什么会这样呢?联合体的大小是怎么计算的呢?它满足两条规则:

  • 联合体的大小至少是其最大成员的大小
  • 当最大成员的大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍
      

图示:

在这里插入图片描述

  通过这图,就能很好地分析出上面两个联合体的大小啦

  
  

1.5、联合体的应用举例

  
  结构体的使用,最主要的是节省空间

  现在有这么一个场景:我们要举办一个活动,要上线一个礼品兑换单,兑换单中有三种商品:图书、杯子、衬衫。每一种商品都有:库存量,价格、商品类型以及和商品类型相关的其他信息

  • 图书:书面、作者、页数
  • 杯子:设计
  • 衬衫:设计、可选颜色、可选尺寸

  我们不耐心思考,直接写出一下结构

struct gift_list
{//公共属性int stock_number;//库存量double price;//定价int item_type;//商品类型//特殊属性char title[20];//书名char autor[20];//作者int num_pages;//页数char design[30];//设计int colors;//颜色int sizes;//尺寸
};

  
  上述的结构设计的其实很简单,用起来也很方便,但是结构汇的设计中包含了所有礼品的各种属性,这样使得结构体的大小就会偏大,比较浪费内存。因为对于礼品兑换单种的商品来说,只有部分属性信息是常用的,比如:
  
  商品时图书,就不需要 d e s i g n design design c o l o r s colors colors s i z e s sizes sizes
  
  所以我们就可以把公共属性单独写出来,剩余属于各种商品本身的属性使用联合体这样就可以减少内存所需要的内存空间,一定程度上节省了内存。
  

struct gift_list
{//公共属性int stock_number;//库存量double price;//定价int item_type;//商品类型//特殊属性union {struct{char title[20];//书名char autor[20];//作者int num_pages;//页数}book;struct{char design[30];//设计}mug;struct{char design[30];//设计int colors;//颜色int sizes;//尺寸}shirt;};
};

  
  

二、枚举

2.1、枚举类型的声明

  C语言中枚举是什么?没错,就是你想的那个枚举
  枚举就是一一列举
  把可能的取值一 一列举
  当然,一 一列举的前提是他是有限个数
  
比如:

  • 一周的天数是有限的,7天,可以一一列举
  • 性别有:男、女、保密,可以一一列举
  • 三原色,可以一一列举
      

这些数据的表示就可以使用枚举了

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

  
  上述定义的 e n u m enum enum D a y Day Day e n u m enum enum S e x Sex Sex e n u m enum enum C o l o r Color Color 就是枚举类型
  而{}中的内容就是可能的取值,也叫枚举常量
  这些可能取值都是有值的,默认从 0 开始,依次往后递增 1
  
当然,我们定义枚举类型时,也可以自己给它赋初值

enum Coloe//颜色
{RED = 2,GREEN = 4,BLUE = 8
};

  
  

2.2、枚举类型的优点

  我们可以用 # d e f i n e define define 为什么还要用枚举呢?
  
相比与 # d e f i n e define define,枚举有以下优点

  • 增加代码的可读性可维护性
  • 和 # d e f i n e define define 定义的标识符相比,枚举类型有类型检查,更加严谨
  • 便于调试,预处理阶段会替换 # d e f i n e define define 定义的符号
  • 方便使用,一次可定义多个常量
  • 枚举常量是遵从作用域规则的,枚举声明在函数范围内,只能在该函数内部使用。
      

枚举类型的使用

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

  那我们不禁想:是否可以拿整数给枚举常量赋值呢?在 C语言 中是可以的,但是在 C++ 是不行的,C++ 的类型检查比较严格。
  
  
  
  


  好啦,本期关于联合体与枚举的知识就介绍到这里啦,希望本期博客能对你有所帮助。同时,如果有错误的地方请多多指正,让我们在C语言的学习路上一起进步!

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

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

相关文章

学习R语言第五天

文章目录 语法学习创建数据的方式绘制图形的方式图形添加颜色如何操作数据的方式数据进行验算的判断加付值的方式修改变量名称的方式判断是否存在缺失值在计算的方式忽略缺失值通过函数的方式忽略缺失值日期处理的方式字符串转化成日期的方式格式化数据框中数据返回当前的日期的…

19_Scala集合概述

文章目录 集合回顾javaScala集合三大类String & StringBuilderScala集合两大类 集合 回顾java scala与Java有所不同 函数式编程语言更侧重集合本身提供的哪些功能&#xff1b; Scala集合三大类 1.Seq 存储有序数据可重复 类比 List 2.Set 存储无序数据不可重复 3.Map…

【算法系列】字符串

目录 leetcode题目 一、最长公共前缀 二、最长回文子串 三、二进制求和 四、字符串相加 五、字符串相乘 六、仅仅反转字母 七、字符串最后一个单词的长度 八、验证回文串 九、反转字符串 十、反转字符串 II 十一、反转字符串中的单词 III leetcode题目 一、最长公…

frp内网穿透服务搭建与使用

frp内网穿透服务搭建与使用 1、frp简介 frp 是一个专注于内网穿透的高性能的反向代理应用&#xff0c;支持 TCP、UDP、HTTP、HTTPS 等多种协议。 可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。frp工作原理 服务端运行&#xff0c;监听一个主端口…

Parts2Whole革新:多参照图定制人像,创新自定义肖像生成框架!

DeepVisionary 每日深度学习前沿科技推送&顶会论文分享&#xff0c;与你一起了解前沿深度学习信息&#xff01; Parts2Whole革新&#xff1a;多参照图定制人像&#xff0c;创新自定义肖像生成框架&#xff01; 引言&#xff1a;探索多条件人像生成的新篇章 在数字内容创作…

论文精读-存内计算芯片研究进展及应用

文章目录 论文精读-存内计算芯片研究进展及应用概述背景介绍前人工作 存内计算3.1 SRAM存内计算3.2 DRAM存内计算3.3 ReRAM/PCM存内计算3.4 MRAM存内计算3.5 NOR Flash存内计算3.6 基于其他介质的存内计算3.7 存内计算芯片应用场景 总结QA 论文精读-存内计算芯片研究进展及应用…

SpringBoot中实现发送邮件

概要 在Spring Boot中发送电子邮件相对简单。你可以使用Spring的邮件支持来实现这一点。 步骤&#xff1a; 1.添加依赖&#xff1a;首先&#xff0c;需要在你的pom.xml文件中添加Spring Boot的邮件发送器依赖。 2. 配置邮件服务器&#xff1a;在application.properties或app…

嵌入式全栈开发学习笔记---C语言笔试复习大全14

目录 指针初级 指针的概念 指针类型 指针类型长度 指针的定义 通过指针访问数据 p1和*p1的区别 指针做函数参数 上一篇复习了8道编程题&#xff0c;这篇开始正式复习之指针&#xff01; 说明&#xff1a;我们学过单片机的一般都是有C语言基础的了&#xff0c;网上关于C…

网络 IO 模式

同步 IO 与异步 IO 同步 IO 和异步 IO 是关于数据读写方式的两种不同模式。 同步 IO 是指在程序读写数据时&#xff0c;需要等待操作完成后才能继续执行后面的程序。这种模式下&#xff0c;当程序使用阻塞式 IO 时&#xff0c;会一直等待IO操作完成&#xff0c;程序会暂停执行…

​​【收录 Hello 算法】3.3 数字编码

目录 3.3 数字编码 3.3.1 原码、反码和补码 3.3.2 浮点数编码 3.3 数字编码 Tip 在本书中&#xff0c;标题带有 * 符号的是选读章节。如果你时间有限或感到理解困难&#xff0c;可以先跳过&#xff0c;等学完必读章节后再单独攻克。 3.3.1 原码、反码和补码 在…

一、RocketMQ基本概述与部署

RocketMQ基本概述与安装 一、概述1.MQ概述1.1 用途1.2 常见MQ产品1.3 MQ常用的协议 2.RocketMQ概述2.1 发展历程 二、相关概念1.基本概念1.1 消息&#xff08;Message&#xff09;1.2 主题&#xff08;Topic&#xff09;1.3 标签&#xff08;Tag&#xff09;1.4 队列&#xff0…

RK3576芯片规格,以及与RK3588对比

瑞芯微RK3576是一款高性能、低功耗的SoC&#xff08;系统级芯片&#xff09;处理器&#xff0c;适用于基于ARM的PC、边缘计算设备、个人移动互联网设备等多种应用场景。它采用Arm架构的八核心CPU&#xff0c;集成了GPU、MCU、NPU、VPU等多种计算核心&#xff0c;并具有丰富的外…

Go Web 开发 Demo【用户登录、注册、验证】

前言 这篇文章主要是学习怎么用 Go 语言&#xff08;Gin&#xff09;开发Web程序&#xff0c;前端太弱了&#xff0c;得好好补补课&#xff0c;完了再来更新。 1、环境准备 新建项目&#xff0c;生成 go.mod 文件&#xff1a; 出现报错&#xff1a;go: modules disabled by G…

ttkbootstrap界面美化系列之Menubutton(五)

一&#xff1a;Menubutton接口 print(help(help(ttk.Menubutton))) Help on class Menubutton in module tkinter.ttk:class Menubutton(Widget)| Menubutton(masterNone, **kw)|| Ttk Menubutton widget displays a textual label and/or image, and| displays a menu wh…

Qt | QComboBox(组合框)

01、上节回顾 Qt 基础教程合集02、QComBox 一、QComboBox 类(下拉列表、组合框) 1、QComboBox 类是 QWidget 类的直接子类,该类实现了一个组合框 2、QComboBox 类中的属性 ①、count:const int 访问函数:int count() const; 获取组合框中的项目数量,默认情况下,对于空…

动态规划——路径问题:LCR 166.珠宝的最高价值

文章目录 题目描述算法原理1.状态表示&#xff08;题目经验&#xff09;2.状态转移方程3.初始化4.填表顺序5.返回值 代码实现CJava 题目描述 题目链接&#xff1a;LCR 166.珠宝的最高价值 算法原理 1.状态表示&#xff08;题目经验&#xff09; 对于这种路径类的问题&…

Windows系统和unbtun系统连接usb 3.0海康可见MVS和红外艾睿相机

一.海康可见USB3.0工业面阵相机 海康usb相机需要去海康官网上下载对应系统的MVS客户端及SDK开发包 海康机器人-机器视觉-下载中心 选择Windows系统和unbtun&#xff08;我是linux aarch64,所以选择了对应压缩包解压&#xff09; Windows系统 1.双击安装包进入安装界面&…

自学错误合集--项目打包报错,运行报错持续更新中

java后端自学错误总结 一.项目打包报错2.项目打包之后运行报错 二.项目运行报错 一.项目打包报错 javac: &#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ļ&#xfffd;: E:\xx\xx\xx\docer-xx\src\main\java\xx\xx\xx\xx\xx\xx.java &#xfffd;&#xff…

C/C++ BM30 二叉搜索树与双向链表

文章目录 前言题目解决方案一1.1 思路阐述1.2 源码 解决方案二2.1 思路阐述2.2 源码 总结 前言 这道题要明白二叉搜索树的概念&#xff0c;同时还要对链表的知识比较熟悉。 题目 输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个排序的双向链表。如下图所示 数据范…

鸿蒙开发接口Ability框架:【@ohos.application.missionManager (missionManager)】

missionManager missionManager模块提供系统任务管理能力&#xff0c;包括对系统任务执行锁定、解锁、清理、切换到前台等操作。 说明&#xff1a; 本模块首批接口从API version 8开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 impo…