第十八讲:联合和枚举

第十八讲:联合和枚举

  • 1.联合体(共用体)
    • 1.1联合体的声明
    • 1.2联合体大小的计算
    • 1.3联合体的特点
    • 1.4联合体的使用
      • 1.4.1联合体的直接使用
      • 1.4.2联合体直接使用的优化方法
      • 1.4.3联合体成员中含有数组的使用
      • 1.4.4使用联合体判断当前机器是大端排序,还是小端排序
    • 1.5联合体的具体使用例子
  • 2.枚举类型
    • 2.1枚举类型的声明
    • 2.2枚举成员值的讨论
      • 2.2.1原顺序
      • 2.2.2自己进行赋值
    • 2.3枚举的优点
    • 2.4枚举类型的使用
      • 2.4.1使用1
      • 2.4.2使用2

1.联合体(共用体)

1.1联合体的声明

联合体和结构体相似,联合体也是由一个或多个成员构成,这些成员可以是不同的类型,但是与结构体不同的是,联合体只为最大的成员分配足够的内存空间,而联合体的成员公用同一块内存空间,所以联合体也叫共用体,联合体的声明如下:

//1.1联合体的声明
//联合体的声明与结构体类似
union Book
{char name[10];int id;
};int main()
{//联合体变量的定义union Book b1 = { 0 };return 0;
}

1.2联合体大小的计算

对于下面的一串代码,联合体变量b1的大小是多少,为什么:

union Book
{char name;int id;
};int main()
{//联合体变量的定义union Book b1 = { 0 };//联合体变量的大小printf("%zd\n", sizeof(b1));return 0;
}

b1的大小为4,这就是因为:

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

例如:

//计算联合体的大小
union Un1
{char c[5];//对齐数:1//占五个字节int i;//对齐数:4//占4个字节//所以最大为5个字节,不是4的整数倍,补齐,解果为8
};
union Un2
{short c[7];//14个字节int i;//4个字节//一共为14个字节,不是4的倍数,补齐为16
};
int main()
{printf("%zd\n", sizeof(union Un1));//8printf("%zd\n", sizeof(union Un2));//16return 0;
}

1.3联合体的特点

既然联合体的成员共用同一块内存空间,那我们不妨来分析一下:

//联合类型的声明
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;
}

它们的结果为:
在这里插入图片描述
它们的地址是相同的,所以它们指向同一块内存空间的地址,那既然指向同一块空间的地址,对于其中的一个成员进行赋值,其他成员会受到影响吗:

//联合类型的声明
union Un
{char c;int i;
};
int main()
{//联合变量的定义union Un un = { 0 };un.i = 0x11223344;//先给i赋值,内存中存储的是:44332211(小端排序)un.c = 0x55;//给c赋值,此时内存中存储的是:55332211,显然会影响i的值1printf("%x\n", un.i);//i在内存中的存储被改变为:55332211,所以输出的结果为11223355return 0;
}

我们可以画图来理解:
在这里插入图片描述

1.4联合体的使用

1.4.1联合体的直接使用

//1.4.1联合体的直接使用
union Score
{int score1;int score2;
};int main()
{//因为score1和score2占用同一块内存空间,所以在使用时尽量一个一个进行使用:union Score s1;s1.score1 = 20;//使用score1...(例如:进行打印)printf("%d\n", s1.score1);//使用完s1之后,在使用s2:s1.score2 = 30;//使用score2...(例如:进行打印)printf("%d\n", s1.score2);//这样才能正确使用score1和score2,否则在使用score1时对score2进行操作很可能改变score1的值return 0;
}

1.4.2联合体直接使用的优化方法

上面的代码中,如果想要在一定时间内多次使用多种成员时,无法实现,所以我们探讨解决方法:

//1.4.2联合体直接使用的优化方法
union Score
{int score1;int score2;
};int main()
{union Score s1;s1.score1 = 20;//可以先创建一个保存score1值的变量int pscore1 = s1.score1;//这时我们就可以使用score2了:s1.score2 = 30;//再创建一个保存score2值的变量int pscore2 = s1.score2;//这时想要使用score1,就要将pscore1的值再传给score1:s1.score1 = pscore1;//使用score1...(例如:进行打印)printf("%d\n", s1.score1);return 0;
}

1.4.3联合体成员中含有数组的使用

当联合体成员中包含数组时,情况就有所不同:
在这里插入图片描述

如果我们这样进行赋值的话,可以看到它报错了,正确的使用方法如下:

  1. 使用strcpy函数
union Book
{char name[20];int price;
};int main()
{union Book b1;//先确定书的价钱b1.price = 20;//再确定书的名字//先对结构体进行清空memset(&b1, 0, sizeof(b1));//再使用strcpy函数进行赋值strcpy(b1.name, "tangjiasnashao");return 0;
}
  1. 使用循环
union Book
{char name[20];int price;
};int main()
{union Book b1;//先确定书的价钱b1.price = 20;//再确定书的名字memset(&b1, 0, 20);const char arr[20] = "tangjiasnashao";for (int i = 0; i < strlen(arr); i++)b1.name[i] = arr[i];return 0;
}
  1. 使用标准I/O函数
union Book
{char name[20];int price;
};int main()
{union Book b1;//先确定书的价钱b1.price = 20;//再确定书的名字memset(&b1, 0, 20);scanf("%s", b1.name);return 0;
}

使用fegts函数时换行符也会被存储,需要额外处理:

union Book
{char name[20];int price;
};int main()
{union Book b1;//先确定书的价钱b1.price = 20;//再确定书的名字memset(&b1, 0, 20);fgets(b1.name, 10, stdin);return 0;
}

1.4.4使用联合体判断当前机器是大端排序,还是小端排序

//1.4.4使用联合体判断当前机器是大端排序,还是小端排序
union Test
{char a;int b;
};int main()
{union Test t1;t1.b = 1;if (t1.a == 0)printf("大端排序\n");if(t1.a == 1)printf("小端排序\n");return 0;
}

1.5联合体的具体使用例子

看到联合体的使用如此繁琐,我们是不是感觉:还没有结构体好用,那么就让我们看一下联合体的具体使用:

⽐如,我们要搞⼀个活动,要上线⼀个礼品兑换单,礼品兑换单中有三种商品:图书、杯⼦、衬衫。
每⼀种商品都有:库存量、价格、商品类型和商品类型相关的其他信息:
在这里插入图片描述
我们对它们进行分析:

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;//尺⼨
};

如果我们直接创建结构体的话,会占用很多内存,所以我们可以这样使用:

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

2.枚举类型

2.1枚举类型的声明

枚举其实就是⼀⼀列举

比如:

1.⼀周的星期⼀到星期⽇是有限的7天,可以⼀⼀列举
2.性别有:男、⼥、保密,也可以⼀⼀列举
3.⽉份有12个⽉,也可以⼀⼀列举
4.三原⾊,也是可以⼀⼀列举

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

//枚举的声明
enum Day //星期
{Mon, //每个成员后边需要加逗号Tues,Wed,Thur,Fri,Sat,Sun //最后一个成员后边不用加逗号
};enum Sex//性别
{MALE,FEMALE,SECRET
};enum Color//颜⾊
{RED,GREEN,BLUE
};

2.2枚举成员值的讨论

对于枚举成员,它们其实是有值的,我们现在对它们的值进行讨论:

2.2.1原顺序

//2.2.1原顺序
enum Day //星期
{Mon,Tues,Wed,Thur,Fri,Sat,Sun
};int main()
{printf("%d\n", Mon); //0printf("%d\n", Tues); //1printf("%d\n", Wed); //2printf("%d\n", Thur);//3printf("%d\n", Fri); //4printf("%d\n", Sat); //5printf("%d\n", Sun); //6return 0;
}

可见它们的值是从0开始,往后加的

如果我们想要自己给枚举成员赋值,也是可行的,但是只能在创建枚举类型时进行赋值,不能在main函数或其他函数中进行更改

2.2.2自己进行赋值

//2.2.2情况1
enum Day //星期
{Mon,Tues,Wed = 7,Thur,Fri,Sat,Sun
};int main()
{printf("%d\n", Mon); //0printf("%d\n", Tues); //1printf("%d\n", Wed); //7printf("%d\n", Thur);//8printf("%d\n", Fri); //9printf("%d\n", Sat); //10printf("%d\n", Sun); //11return 0;
}

2.3枚举的优点

当然我们可以使用define定义常量,那为什么要使用枚举呢

枚举的优点:

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

2.4枚举类型的使用

2.4.1使用1

enum Color//颜⾊
{RED=1,GREEN=2,BLUE=4
};int main()
{enum Color clr = GREEN;//使⽤枚举常量给枚举变量赋值//后续可以通过这个值进行判断,比如:if (clr == 	GREEN)printf("YES");return 0;
}

2.4.2使用2

比如当我们想要写一个简单的计算器时,会这样写:

int add(int a, int b)
{return a + b;
}
int sub(int a, int b)
{return a - b;
}
int mul(int a, int b)
{return a * b;
}
int div(int a, int b)
{return a / b;
}
int main()
{int x, y;int input = 1;int ret = 0;do{printf("*************************\n");printf(" 1:add 2:sub \n");printf(" 3:mul 4:div \n");printf(" 0:exit \n");printf("*************************\n");printf("请选择:");scanf("%d", &input);switch (input){case 1:printf("输⼊操作数:");scanf("%d %d", &x, &y);ret = add(x, y);printf("ret = %d\n", ret);break;case 2:printf("输⼊操作数:");scanf("%d %d", &x, &y);ret = sub(x, y);printf("ret = %d\n", ret);break;case 3:printf("输⼊操作数:");scanf("%d %d", &x, &y);ret = mul(x, y);printf("ret = %d\n", ret);break;case 4:printf("输⼊操作数:");scanf("%d %d", &x, &y);ret = div(x, y);printf("ret = %d\n", ret);break;case 0:printf("退出程序\n");break;default:printf("选择错误\n");break;}} while (input);return 0;
}

这样写可读性低,此时我们可以使用枚举:
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

K8s(Kubernetes)常用命令

大家好&#xff0c;当谈及容器编排工具时&#xff0c;Kubernetes&#xff08;常简称为K8s&#xff09;无疑是当今最受欢迎和广泛使用的解决方案之一。作为一个开源的容器编排平台&#xff0c;Kubernetes 提供了丰富的功能&#xff0c;可以帮助开发人员和运维团队管理、部署和扩…

电商分析@电商数据与运营优化

电商数据分析与运营优化是指通过对电商平台的各种数据进行深入分析&#xff0c;以发现潜在的问题和机会&#xff0c;并采取相应的优化措施&#xff0c;提高电商运营效率和盈利能力。 首先&#xff0c;电商数据分析需要收集和整理各类数据&#xff0c;包括销售数据、用户数据、流…

实战16:基于apriori关联挖掘FP-growth算法挖掘关联规则的手机销售分析-代码+数据

直接看视频演示: 基于apriori关联挖掘关联规则的手机销售分析与优化策略 直接看结果: 这是数据展示: 挖掘结果展示: 数据分析展示:

利用WK2168实现串口服务器

ESP32 SPI与WK2168实现串口服务器 概述系统组成代码概述 一些老设备通过RS485采集数据,如果在一个系统中采用几个RS485设备可能是一个不错的选择,但要是使用46个RS485数据采集设备为一个PLC提供外部数据,系统的性能就很难有保障了。通过一个串口服务器实现看来是一个好的选…

智慧校园有哪些特征

随着科技的飞速进步&#xff0c;教育领域正经历着一场深刻的变革。智慧校园&#xff0c;作为这场变革的前沿代表&#xff0c;正在逐步重塑我们的教育理念和实践方式。它不仅仅是一个概念&#xff0c;而是一个集成了物联网、大数据、人工智能等先进技术的综合生态系统&#xff0…

SpringBoot源码(自动装配、内嵌Tomcat)

文章目录 依赖管理pom依赖管理Web依赖自定义starter 一、WebMvcAutoConfiguration1.1 Filter1.2 Interceptor 二、源码解析2.1 SpringApplication2.1.1 构造方法1、填充webApplicationType2、自动装配Initializers3、自动装配Listeners 2.1.2 run(args) 2.2 SpringApplicationR…

AI边缘计算盒子在智慧交通的应用

方案背景 随着经济增长&#xff0c;交通出行需求大幅增长&#xff0c;但道路建设增长缓慢&#xff0c;交通供需矛盾日益显著&#xff0c;中心城区主要道路高峰时段交通拥堵严重&#xff0c;道路交通拥堵逐渐常态化&#xff0c;成为制约城市可持续发展的重要因素之一。 痛点问题…

web 前端开发技术---网页的制作

这是一个网页代码 上年包含了电子邮件&#xff0c;选项建 等等 分享给大家 <!-- prj_7_1.html --> <!DOCTYPE html> <html lang"en"><head><meta charset"utf-8"><title>留言板设计</title><style type&…

【C++】入门(一):命名空间、缺省参数、函数重载

目录 一、关键字 二、命名空间 问题引入(问题代码)&#xff1a; 域的问题 1.::域作用限定符 的 用法&#xff1a; 2.域的分类 3.编译器的搜索原则 命名空间的定义 命名空间的使用 举个&#x1f330;栗子&#xff1a; 1.作用域限定符指定命名空间名称 2. using 引入…

K210视觉识别模块学习笔记3:内存卡写入拍摄图片_LED三色灯的操作_按键操作_定时器的配置使用

今日开始学习K210视觉识别模块: LED三色灯的操作_按键操作_定时器的配置使用_内存卡写入拍摄图片 亚博智能的K210视觉识别模块...... 本文最终目的是编写一个按键拍照的例程序&#xff1a; 为以后的专用场景的模型训练做准备&#xff0c;因为训练自己的模型需要大量的图片&a…

编译安装PHP服务(LAMP3)

目录 1.初始化设置&#xff0c;将安装PHP所需软件包传到/opt目录下 &#xff08;1&#xff09;关闭防火墙 &#xff08;2&#xff09;上传软件包到/opt目录 2.安装GD库和GD库关联程序&#xff0c;用来处理和生成图片 3.配置软件模块 4.编译及安装 5.优化把PHP 的可执行程…

nginx的安装001

Nginx是一款高性能的HTTP和反向代理服务器&#xff0c;以及邮件代理服务器&#xff0c;由 Igor Sysoev 开发并公开发布于2004年。Nginx以其高并发处理能力、低内存消耗和稳定性著称&#xff0c;特别适合部署在高流量的网站上。 操作系统&#xff1a; CentOS Stream 9 安装步骤…

企业如何利用社交媒体二维码做宣传?提升品牌形象

和普通的二维码不同&#xff0c;社交媒体二维码可以通过一个二维码链接企业的超过16的社交媒体渠道链接&#xff0c;包括&#xff1a;企业官网、小程序、公众号、淘宝店铺、抖音链接、小红书链接、美团链接、饿了么链接…等等。扫描之后&#xff0c;可以在这个社交媒体二维码界…

校园志愿者|基于SprinBoot+vue的校园志愿者管理系统(源码+数据库+文档)

校园志愿者管理系统 目录 基于SprinBootvue的校园志愿者管理系统 一、前言 二、系统设计 三、系统功能设计 1 系统功能模块 2管理员功能 3志愿者功能 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&a…

12.RedHat认证-Linux文件系统(下)

12.RedHat认证-Linux文件系统(下) swap虚拟内存 我加一个硬盘做实验sdc # 创建交换分区&#xff08;不用做成逻辑卷也能灵活分区&#xff09; [rootcentos8 ~]# fdisk /dev/sdc -l Disk /dev/sdc&#xff1a;10 GiB&#xff0c;10737418240 字节&#xff0c;20971520 个扇区 …

深入理解linux文件系统与日志分析

深入理解linux文件系统与日志分析 linux文件系统: 文件是存储在硬盘上的&#xff0c;硬盘上的最小存储单位是扇区&#xff0c;每个扇区的大小是512字节。 inode&#xff1a;元信息&#xff08;文件的属性 权限&#xff0c;创建者&#xff0c;创建日期等等&#xff09; block…

【AVL Design Explorer DOE】

AVL Design Explorer DOE 1、关于DOE的个人理解2、DOE参考资料-知乎2.1 DOE发展及基本类型2.2 DOE应用场景2.3 Mintab 中的 DOE工具3、AVL Design Explorer DOE示例 1、关于DOE的个人理解 仿真和试验一样&#xff0c;就像盲人摸象&#xff0c;在不知道大象的全景之前&#xff…

Java 垃圾回收

一、概述 GC GC(Garbage Collection)&#xff0c;在程序运行过程中内存空间是有限的&#xff0c;为了更好的的使用有限的内存空间&#xff0c;GC会将不再使用的对象清除然后将其所占用的内存释放出来。 java的垃圾回收机制 Java的垃圾收集&#xff08;Garbage Collection, …

嵌入式Linux复制剪切删除指令详解

指令操作 1. cp 复制指令 a. 用法&#xff1a;cp [ 选项 ] [ 源文件或目录 ] [ 目标文件或目录 ]&#xff1b; b. 用途&#xff1a;用于复制文件或目录&#xff1b; c. 通常情况下&#xff0c;复制的都不是空文件夹&#xff0c;所以直接使用 cp 复制空文件会失败&#xff0…

臭氧浓度传感器在食品厂与制药厂中的应用

在食品厂和制药厂的生产过程中&#xff0c;消毒是一个至关重要的环节。有效的消毒可以确保产品免受微生物污染&#xff0c;从而保障消费者的健康。近年来&#xff0c;臭氧作为一种广谱杀菌剂&#xff0c;因其强效的消毒能力和低污染性&#xff0c;在食品厂和制药厂的消毒过程中…