C语言自定义类型【联合体与枚举】

文章目录

  • 1.联合体
    • 1.1联合体的声明
    • 1.2联合体的特点
    • 1.3联合体的大小计算
      • 联合体的使用案例
  • 2.枚举
    • 2.1枚举类型的声明
    • 2.2枚举类型的优点(为什么使用枚举)
    • 2.3枚举类型的使用
  • 结语

1.联合体

1.1联合体的声明

和结构体一样,联合体也是由一个或多个成员构成,同样,这些成员也可以是不同的类型。
但是,编译器只会为最大的成员分配足够的内存空间。联合体的特点是所有成员共用同一块内存空间。所以,联合体也叫共用体

#include<stdio.h>
//联合体的声明
union Un
{
	char c1;
	int i;
	char c2;
};

int main()
{
	//创建一个union Un类型的临时变量
	union Un un = { 0 };
	//计算联合体变量的大小
	printf("union Un 大小为%zd", sizeof(un));
	return 0;
}

在这里插入图片描述

为什么是4呢?
我们就来了解联合体的特点吧

1.2联合体的特点

联合的成员是共用同一块内存空间,所以一个联合体变量的大小至少是最大成员的大小(因为联合至少得有能力存放最大的成员)。

#include<stdio.h>
//联合体的声明
union Un
{
	char c1;
	int i;
};

int main()
{
	//创建一个union Un类型的临时变量
	union Un un = { 0 };
	//查看联合成员的地址
	printf("成员i 的地址为  %p\n", &un.i);
	printf("成员c1的地址为  %p\n", &un.c1);
	printf("联合体un的地址为%p\n", &un.c1);

	return 0;
}

在这里插入图片描述
可以看到输出的三个地址一模一样。

#include<stdio.h>

//联合体的声明
union Un
{
	char c1;
	int i;
};

int main()
{
	//创建一个union Un类型的临时变量
	union Un un = { 0 };
	un.i = 0x11223344;
	un.c1 = 0x55;
	//查看联合体成员的值(16进制)
	printf("成员i的为%x\n", un.i);

	return 0;
}

在这里插入图片描述

在这里插入图片描述
我们通过调试可以看到,i的第4个字节的内容被修改为了55。
在这里插入图片描述
在这里插入图片描述
这又证明了,联合体的所有成员是共用同一块空间。

成员相同的结构体和联合体进行比较

#include<stdio.h>

struct Str
{
	char c1;
	int i1;
};

union Un
{
	char c2;
	int i2;
};

int main()
{
	printf("struct Str的大小为%zd\n", sizeof(struct Str));
	printf("union Un的大小为%3zd", sizeof(union Un));

	return 0;
}

在这里插入图片描述
他们的成员大小相同,成员顺序相同,但输出的结果还是不同,也就是说结构体和联合体对待成员的存放是不同的。
结构体每个成员有独立的空间,而联合体是共用一块空间

1.3联合体的大小计算

1.联合体的大小至少是最大成员的大小
2.如果最大成员的大小不是最大对齐数的整数倍时,空间大小要对齐到最大对齐数的整数倍
看代码:

union Un1//最大对齐数为4(int)
{
	char ch[5];//大小为5(最大)
	int i;//大小为4
};

union Un2//最大对齐数为4(int)
{
	short sh[5];//大小为10(最大)
	int i;//大小为4
};

union Un3//最大对齐数为8(long long)
{
	int arr[5];//大小为20(最大)
	long long lg;//大小为8
};

int main()
{
	printf("union Un1的大小为%zd\n", sizeof(union Un1));
	printf("union Un2的大小为%zd\n", sizeof(union Un2));
	printf("union Un3的大小为%zd\n", sizeof(union Un3));
	return 0;
}

在这里插入图片描述

联合体的使用案例

联合体的使用案例
假如我们要搞⼀个活动,要上线⼀个礼品兑换单
礼品兑换单中有三种商品:图书、杯⼦、衬衫。
每种商品都有:库存,价格,商品类型,我们称之为公共属性
其中每个商品有各自的特殊属性
图书:书名,作者,页数
杯子:设计方案
衬衫:设计方案,颜色,尺寸

解决方法一:

struct gift_list
{
	//公共属性
	int stock_number;//库存
	double price;//价格
	int item_type;//商品类型

	//特殊属性
	char Title[20];//书名
	char Author[20];//作者
	int Num_page;//页数

	char Design;//设计方案(杯子和衬衫都有设计方案)
	char Colors[10];//颜色
	int Size;//尺寸

};

上面的的代码,很暴力,也很方便,但是结构的设计中包含了所有礼物的属性,这样会使得结构体的大小会偏大,比较浪费空间。而且对于单个商品来说,只有部分属性是我要用的。

比如商品是衬衫的话我要用的就是Design、Colors、Size,而Title、Author、Num_page就是不需要的属性

所有我们可以把公共属性独立写出来,剩余各种商品本身的特殊属性就可以使用联合体。这样就可以在一定程度上节省空间。

struct Gift_List
{
	//公共属性
	int stock_number;//库存
	double price;//价格
	int item_type;//商品类型

	union MyUnion
	{
		struct
		{
			char Title[20];//书名
			char Author[20];//作者
			int Num_page;//页数
		}book;

		struct 
		{
			char Design;//设计方案(杯子和衬衫都有设计方案)
		}mug;

		struct 
		{
			char Design;//设计方案(杯子和衬衫都有设计方案)
			char Colors[10];//颜色
			int Size;//尺寸
		}shirt;
	}item;
};

2.枚举

2.1枚举类型的声明

顾名思义就是将可能的元素进行一一列举
例如我们生活中的:一周的星期一到星期日、十二个月份、三原色;这些都可以一一列举
附上代码

enum Colors//
{
	RED,
	BLUE,
	GREEN
};

enum Week_By_Day
{
	Mon,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};

以上定义的 颜色一周都是枚举类型。
而{}里的内容是枚举类型里的可能取值,这也叫做枚举常量。

这些可能取值都是有值的(创建常量的时候肯定是要赋值的)
枚举常量默认从0开始,依次递增1,当然,在声明枚举类型的时候也可以赋初始值。

enum Direction
{
	NORTH,//初始值在没有赋值的情况下就是0
		  //后面的值发生改变也不会改变前面的值
	EAST,
	WEST = 5,
	SOUTH
};

int main()
{
	printf("%d\n", NORTH);
	printf("%d\n", EAST);
	printf("%d\n", WEST);
	printf("%d\n", SOUTH);
	return 0;
}

在这里插入图片描述
初始值在没有赋值的情况下就是0,后面的值发生改变也不会改变前面的值

2.2枚举类型的优点(为什么使用枚举)

明明我们有#define 来定义常量,为什么要使用枚举?

1.增加代码的可读性和可维护性
2.和#define定义的标识符进行比较,枚举有类型检查,更加严谨
3.便于调试,预处理阶段会直接将#define定义的符号替换为原来的符号
4.使用更方便,一次可以定义多个常量
5.枚举常量是遵循作用域规则的,枚举声明在某个函数内,只能在该函数内部使用

2.3枚举类型的使用

#include<stdio.h>
enum Colors
{
	RED,//0
	BLUE,//1
	GREEN//2
};
int main()
{
	enum Color clr = GREEN;//使⽤枚举常量给枚举变量赋值
	printf("clr的值为%d", clr);
	return 0;
}

在这里插入图片描述

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

结语

最后感谢您能阅读完此片文章,如果有任何建议或纠正欢迎在评论区留言。如果您认为这篇文章对您有所收获,点一个小小的赞就是我创作的巨大动力,谢谢

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何在 Visual Studio 中通过 NuGet 添加包

在安装之前要先确定Nuget的包源是否有问题。 Visual Studio中怎样更改Nuget程序包源-CSDN博客 1.图形界面安装 打开您的项目&#xff0c;并在解决方案资源管理器中选择您的项目。单击“项目”菜单&#xff0c;然后选择“管理 NuGet 程序包”选项。在“NuGet 包管理器”窗口中…

CTF(web方向)--md5的“===”和“==”的绕过

一、PHP弱类型说明 1.简介 php是一种弱类型语言&#xff0c;对数据的类型要求并不严格&#xff0c;可以让数据类型互相转换。 在php中有两种比较符号: 一种是 &#xff0c;另外一种是 &#xff0c;都是用来比较两个数值是否相等的操作符&#xff0c;但他们也是有区别的: &a…

大数据架构相关知识总结

一、大数据处理系统架构特性 1. 鲁棒性和容错性&#xff1a; 系统必须对游bug的程序写入的错误数据游足够的适应能力 2. 低延迟读取和更新能力 3. 横向扩容&#xff1a; 可以通过增加机器数量来维持性能 4. 通用性&#xff1a; 需要支持绝大多数应用程序 5. 延展性&#xff1a;…

前端工程化Vue使用Node.js设置国内高速npm镜像源(踩坑记录版)

前端工程化Vue使用Node.js设置国内高速npm镜像源&#xff08;踩坑记录版&#xff09; 此篇仅为踩坑记录&#xff0c;并未成功更换高速镜像源&#xff0c;实际解决方法见文末跳转链接。 1.自身源镜像 自身镜像源创建Vue项目下载速度感人 2.更改镜像源 2.1 通过命令行配置 前提…

【工作】程序员工作压力八个常见来源与建议缓解压力小窍门

目录 ​编辑 一. 程序员工作压力八个常见来源与建议 1&#xff09;目标职位不对 2&#xff09;工作任务描述不清晰 3&#xff09;快节奏的工作环境 4&#xff09;项目后期突然被添加新的要求 5&#xff09;计划外的工作事务会打断并破坏注意力 6&#xff09;个人问题 7…

MySQL第一次作业

解压完安装包 以管理员进入命令行 初始化并记住初始随机密码 创建服务名称 启动mysql 使用随机密码登录 修改密码 退出并重登服务器 MySQL创建数据库和表 创建数据库 创建表 1.进入数据库 创建表 向表中插入数据

鸿蒙OpenHarmony【小型系统 编译】(基于Hi3516开发板)

编译 OpenHarmony支持hb和build.sh两种编译方式。此处介绍hb方式&#xff0c;build.sh脚本编译方式请参考[使用build.sh脚本编译源码]。 使用build.sh脚本编译源码 进入源码根目录&#xff0c;执行如下命令进行版本编译。 ./build.sh --product-name name --ccache 说明&…

[Java EE] 多线程(四):线程安全问题(下)

1.5 volatile关键字 我们在了解这个关键字之前,我们首先要把产生线程安全的第4个原因补齐,我们来说说由于内存可见性引起的线程安全问题. 我们来看下面这样一段代码: import java.util.Scanner;public class Demo16 {public static int count 0;public static void main(Str…

PotatoPie 4.0 实验教程(25) —— FPGA实现摄像头图像直方图均衡变换

图像的直方图均衡是什么&#xff1f; 图像的直方图均衡是一种用于增强图像对比度的图像处理技术。在直方图均衡中&#xff0c;图像的像素值被重新分配&#xff0c;以使得图像的直方图变得更均匀&#xff0c;即各个像素值的分布更加平衡。这意味着直方图中每个像素值的频率大致…

在PR中使用 obs 和 vokoscreen 录制的视频遇到的问题

1. obs 录制的视频 在 Adobe Premiere Pro CS6 中只有音频没有视频 2. vokoscreen 录制的视频&#xff0c;没有声音 这是是和视频录制的编码有关系&#xff0c;也和显卡驱动关系 首先 obs 点击 文件 ---> 设置 录制的视频都是可以正常播放的&#xff0c;在PR不行。更…

python爬虫 - 爬取 json 格式数据(股票行情信息:雪球网,自选股)

文章目录 1. 第一步&#xff1a;安装requests库2. 第二步&#xff1a;获取爬虫所需的header和cookie3. 第三步&#xff1a;获取网页4. 第四步&#xff1a;解析网页5. 第五步&#xff1a;解析 json 结构数据体6. 代码实例以及结果展示 python爬虫五部曲&#xff1a; 第一步&…

字符串变量 字符串常量

仅个人笔记 #include<iostream> using namespace std;int main() {char str[] "2232344434";for (int i 0; i < strlen(str); i){printf("%c", *(stri));}const char* arr "12343545";for (int i 0; i < strlen(arr); i){printf…

HackMyVM-Vulny

目录 信息收集 arp nmap nikto WEB信息收集 主页信息收集 gobuster RCE漏洞 反弹shell 提权 系统信息收集 横向渗透 flock提权 信息收集 arp ┌──(root㉿0x00)-[~/HackMyVM] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC…

mysql-sql-练习题-2-窗口函数

窗口函数 访问量max sum建表窗口函数连接 直播间人数 第1、3名建表排名sum 访问量max sum 每个用户截止到每月为止&#xff0c;最大单月访问次数&#xff0c;累计到该月的总访问次数 建表 create table visit(uid1 varchar(5) comment 用户id,month1 varchar(10) comment 月…

【热门话题】Chrome 插件研发详解:从入门到实践

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 Chrome 插件研发详解&#xff1a;从入门到实践一、引言二、Chrome 插件基础概念…

Win32 API 光标隐藏定位和键盘读取等常用函数

Win32 API 光标隐藏定位和键盘读取等常用函数 一、Win32 API二、控制台程序指令modetitlepausecls 三、控制台屏幕上坐标的结构体COORD四、句柄获取函数GetStdHandle五、控制台光标操作1.控制台光标信息结构体CONSOLE_CURSOR_INFO2.得到光标信息函数GetConsoleCursorInfo3. 设置…

Amazon云计算AWS之[5]关系数据库服务RDS

文章目录 RDS的基本原理主从备份和下读写分离 RDS的使用 RDS的基本原理 Amazon RDS(Amazon Relational Database Service) 将MySQL数据库移植到集群中&#xff0c;在一定的范围内解决了关系数据库的可扩展性问题。 MySQL集群方式采用Share-Nothing架构。每台数据库服务器都是…

《架构风清扬-Java面试系列第25讲》聊聊ArrayBlockingQueue的特点及使用场景

ArrayBlockingQueue是BlockingQueue接口的一个实现类之一 这个属于基础性问题&#xff0c;老规矩&#xff0c;我们将从使用场景和代码示例来进行讲解 来&#xff0c;思考片刻&#xff0c;给出你的答案 1&#xff0c;使用场景 实现&#xff1a;基于数组实现的有界阻塞队列&…

TCP/IP协议族中的TCP(二):解析其关键特性与机制

⭐小白苦学IT的博客主页⭐ ⭐初学者必看&#xff1a;Linux操作系统入门⭐ ⭐代码仓库&#xff1a;Linux代码仓库⭐ ❤关注我一起讨论和学习Linux系统 滑动窗口 在前面我们讨论了确认应答策略, 对每一个发送的数据段, 都要给一个ACK确认应答. 收到ACK后再发送下一个数据段.这样…

【Python】#5 基础文件IO详解

文章目录 一、文件概述二、文件操作1.文件的打开与关闭2. 文件的读写2.1 读取2.2 写入tips:CSV与JSON文件 一些文件操作小实验《清明》文本写入与读取《红楼梦》人物出现统计&#xff08;部分文本&#xff09; 一、文件概述 文件是数据的集合和抽象&#xff0c;类似&#xff0…