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

news2024/11/18 23:28:38

文章目录

  • 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++的类型检查比较严格。

结语

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

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

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

相关文章

ffmpeg中stream_loop参数不生效原因分析

问题 使用ffmpeg把一个视频文件发布成一个rtmp流&#xff0c;并设置成循环推流&#xff0c;此时需要使用参数stream_loop&#xff0c;命令如下: ffmpeg.exe -stream_loop -1 -re -i D:\tools\ffmpeg-5.1.2\bin\sei.h264 -c copy -f flv -safe 0 rtmp://localhost:1935/live/te…

BIO、NIO与AIO

一 BIO 同步并阻塞(传统阻塞型)&#xff0c;服务器实现模式为一个连接一个线程&#xff0c;即客户端有连接请求时服务器端就需要启动一个线程进行处理. BIO&#xff08;Blocking I/O&#xff0c;阻塞I/O&#xff09;模式是一种网络编程中的I/O处理模式。在BIO模式中&#xf…

杂项基础知识-部分

** 杂项基础知识 ** 一.常见的各类文件的文件头和文件结尾 列举常见文件头编码特征&#xff1a; JPEG&#xff1a; PNG&#xff1a; GIF&#xff1a; RAR&#xff1a; ZIP&#xff1a; 十六进制特征&#xff1a; 图片文件&#xff1a; JPEG&#xff1a;文件头格式为…

K8s 使用 CephFS 作为后端存储(静态供给、动态供给)

一、K8s 使用 CephFS CephFS是 Ceph 中基于RADOS&#xff08;可扩展分布式对象存储&#xff09;构建&#xff0c;通过将文件数据划分为对象并分布到集群中的多个存储节点上来实现高可用性和可扩展性。 首先所有 k8s 节点都需要安装 ceph-common 工具&#xff1a; yum -y ins…

C++面经(简洁版)

1. 谈谈C和C的认识 C在C的基础上添加类&#xff0c;C是一种结构化语言&#xff0c;它的重点在于数据结构和算法。C语言的设计首要考虑的是如何通过一个过程&#xff0c;对输入进行运算处理得到输出&#xff0c;而对C&#xff0c;首先要考虑的是如何构造一个对象&#xff0c;通…

PotatoPie 4.0 实验教程(41) —— FPGA实现RISC-V 扩展 GPIO UART Timer功能

TD工程介绍 我们提供的TD工程里的RISC-V核默认就开启了GPIO UART扩展&#xff0c;可以看到还有SPI和I2C扩展。因此后面的实验中TD的工程我们基本不怎么修改TD的内容&#xff0c;只需要修改TD工具中Soc_Top.v文件中的TCM0_INITFILE为FD生成的固件名称即可&#xff0c;主要修我以…

实时通讯技术 WebRTC 介绍

WebRTC WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音对话或视频对话的技术。 历史 2010年5月&#xff0c;Google以6820万美元收购VoIP软件开发商Global IP Solutions的GIPS引擎&#xff0c;并改为名为“WebRTC”。WebRTC使用…

C++ ─── 匿名对象+变量的创建顺序

目录 1. 匿名对象&#xff08;临时对象&#xff09; 2. 编译器的优化 3.变量的创建与销毁 1. 匿名对象&#xff08;临时对象&#xff09; 我们先来看有名对象的创建 Date d1; Date d2(2024,4,27);匿名对象的创建 Date(2024,56,1); 生成了一个匿名对象&#xff0c;执行完Da…

数据仓库是什么

写在前面 刚接触大数据的新手小白可能会对数据仓库这个词比较陌生&#xff0c;本文将介绍数据仓库的主要特征及OLTP&OLAP的区别&#xff0c;帮助读者更好理解数据仓库。 一、什么是数据仓库 数据仓库&#xff0c;简称数仓&#xff0c;是一个对数据进行加工&#xff0c;集…

信息系统项目管理师0073:网路集成(5信息系统工程—5.3系统集成—5.3.2网路集成)

点击查看专栏目录 文章目录 5.3.2网路集成5.3.2网路集成 计算机网络系统集成不仅涉及技术问题,而且涉及组织的管理问题,因而比较复杂,特别是大型网络系统更是如此。从技术角度讲,网络集成不仅涉及不同厂家的网络设备和管理软件,也会涉及异构和异质网络系统的互联问题。从管…

【算法学习】day1

文章目录 双指针算法移动零复写零 双指针算法 移动零 思路&#xff1a;通过定义两个下标作为双指针&#xff0c;cur从开始对整个数组进行遍历&#xff0c;而我们的dest代表的是非零元素的最后一个位置&#xff0c;cur位置为0的时候就cur&#xff0c;不为0元素的时候就交换dest…

STM32单片机C语言模块化编程实战:按键控制LED灯详解与示例

一、开发环境 硬件&#xff1a;正点原子探索者 V3 STM32F407 开发板 单片机&#xff1a;STM32F407ZGT6 Keil版本&#xff1a;5.32 STM32CubeMX版本&#xff1a;6.9.2 STM32Cube MCU Packges版本&#xff1a;STM32F4 V1.27.1 之前介绍了很多关于点灯的方法&#xff0c;比如…

设计模式学习笔记 - 项目实战一:设计实现一个支持各种算法的限流框架(实现)

概述 上篇文章&#xff0c;我们介绍了如何通过合理的设计&#xff0c;来实现框架的功能性需求的同时&#xff0c;满足易用、易扩展、灵活、低延迟、高容错等非功能性需求。在设计的过程中&#xff0c;我们也借鉴了之前讲过的一些开源项目的设计思想。比如 Spring 的低侵入松耦…

【ETAS CP AUTOSAR工具链】RTE层基本概念与开发流程

本篇文章续接上篇文章【ETAS CP AUTOSAR工具链】基本概念与开发流程&#xff0c;继续按上篇文章描述的ETAS CP工具链进行开发的基本框架&#xff0c;讲述了“RTE集成与配置”这部分的基本概念与开发流程。 RTE&#xff08;Runtime Environment&#xff09;处于应用层与基础软件…

Web前端开发 小实训(一) 成绩分类统计

用于学生web前端开发课程实训练习&#xff0c;掌握基本语法和数据类型 实训目的 使用分支语句&#xff0c;完成分数统计与等级对比,通过输入框输入分数&#xff0c;可以根据分数多少划分等级。 参考思路&#xff1a; 分析题目&#xff1a;根据输入分数进行等级划分。 操作过…

声光控路灯控制系统设计与仿真

目录 前言 一、设计任务 二、系统组成及工作原理 1、总体设计思路 2、电路各模块设计简介 &#xff08;1&#xff09;光控电路 &#xff08;2&#xff09;声控电路 (3) 逻辑控制电路 (4) 延时电路 三、系统中电源模块的设计 1、方案比较和确定 2、 设计思路 3、直流…

自定义View-旋转变色圆角三角形的绘制

本文字数&#xff1a;3151字 预计阅读时间&#xff1a;20分钟 在现代设计中&#xff0c;动效图在APP的UI界面中所起到的作用无疑是显著的。相比于静态的界面&#xff0c;动效更符合人类的自然认知体系&#xff0c;它有效地降低了用户的认知负载&#xff0c;UI动效俨然已经成为了…

利用ENVI SPEAR工具和WV-2卫星影像数据量测水深

ENVI的SPEAR工具集&#xff08;(Spectral Processing Exploitation and Analysis Resource)&#xff09;是将很多的遥感图像处理过程集成为流程化的操作方式&#xff0c;使得遥感图像处理知识相对薄弱的非专业人员也能利用流程化的工具进行图像处理&#xff0c;图像处理速度也有…

自动驾驶框架 UniAD环境部署

感谢大佬们的开源工作 UniAD-github地址-YYDS更多bev算法部署参考如果您觉得本帖对您有帮助&#xff0c;感谢您一键三连支持一波^_^ 统一自动驾驶框架 (UniAD) &#xff0c;第一个将全栈驾驶任务整合到一个深度神经网络中的框架&#xff0c;并可以发挥每个子任务以及各个模块的…

[每周一更]-(第94期):认识英伟达显卡

英伟达显卡&#xff1a;引领图形计算的领先者&#xff0c;显卡也常称为GPU&#xff08;图形处理器 Graphics processing unit&#xff09;&#xff0c;是一种专门在个人电脑、工作站、游戏机和一些移动设备&#xff08;如平板电脑、智能手机等&#xff09;上执行绘图运算工作的…