巧用联合与枚举:解锁自定义类型的无限潜力

news2024/9/20 17:38:21

嘿嘿,家人们,今天咱们来详细剖析C语言中的联合与枚举,好啦,废话不多讲,开干!


目录

1.:联合体

1.1:联合体类型的声明

1.1.1:代码1

1.1.2:代码2(计算机联合体的大小)

1.1.3:代码3

1.2:联合体的特点

1.2.1:代码1 

1.2.2:代码2

1.3:相同成员的结构体与联合体进行对比

1.3.1:代码1(结构体)

1.3.2:代码2(联合体)

 ​编辑

1.4:联合体大小的计算

1.4.1:代码1

1.4.2:代码2

1.4.3:联合体的优点

1.4.3.1:结构体描述

1.4.3.2:使用联合体描述 

1.5:联合的一个练习

1.5.1:(通过拿数值1的最低位并且按位与1)

1.5.2:代码2(通过联合体)

2:枚举类型

2.1:枚举类型的声明

2.1.1:代码1 

2.1.2:代码2(给枚举类型赋初值)

2.2:枚举类型的优点

2.3:枚举类型的使用


1.:联合体

1.1:联合体类型的声明

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

1.1.1:代码1

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

union Un
{
	char _c;
	int _i;
};

int main()
{
	//联合变量的定义
	union Un  u1 = {'c'};
	return 0;
}

1.1.2:代码2(计算机联合体的大小)

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

union Un
{
	char _c;
	int _i;
};

int main()
{
	//联合变量的定义
	union Un  u1 = {'c'};

	printf("%d\n", sizeof(u1));
	return 0;
}

在结构体那一章节,博主讲到了,结构体的大小要遵循内存对齐的规则,那么联合体要不要遵从内存对齐的规则,如果遵从的话,上面的代码计算出来的结果是8(原因博主不过多解释哈,忘了滴uu可以去去博主那篇结构体的博客).

1.1.3:代码3

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

union Un
{
	char _c;
	double _i;
};

int main()
{
	//联合变量的定义
	union Un  u1 = {'c'};

	printf("%d\n", sizeof(u1));
	return 0;
}

上面的两段代码输出结果是4与8,那么为什么是4与8呢?这里就要讲到联合体的特点了

1.2:联合体的特点

联合体的成员是共用一块内存空间的,这样一个联合体变量的大小,至少是最大成员的大(因为联合体至少得有能力保存最大的那个成员),而上面的代码中最大成员int类型,因此结果为4

1.2.1:代码1 

#include <stdio.h>
int main()

union Un
{
    char _c;
    int _i;
};
{
    union Un u1 = {0};
    printf("&u1._c == %p\n",&u1._c);
    printf("&u1._i == %p\n",&u1._i);
    printf("&u1 == %p\n",&u1);
    return 0;    
}

上面的代码输出的三个均是一模一样,那么我们仔细便可以画图u1的内存分布图.

1.2.2:代码2

#include <stdio.h>
int main()

union Un
{
    char _c;
    int _i;
};
{
    union Un u1 = { 0 };
    u1._i = 0x11223344;
    u1._c = 0x55;
    printf("%x\n", u1._i);
    return 0;
}

通过上面的代码我们可以分析出,将变量i的第4个字节改成了55,那么因此我们可以画出其对应的内存分布图.

1.3:相同成员的结构体与联合体进行对比

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

1.3.1:代码1(结构体)

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

struct S
{
	char _c;
	int _i;
};

int main()
{
	struct S s1 ={'c'};
	return 0;
}

1.3.2:代码2(联合体)

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

union Un
{
	char _c;
	int _i;
};

int main()
{
	union Un u = {0};
	return 0;
}

 

1.4:联合体大小的计算

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

1.4.1:代码1

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

union Un1
{
	char c[5];
	int _i;
};

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

1.4.2:代码2


#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

union Un2
{
	short s[5];
	int _i;
};

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

1.4.3:联合体的优点

使用联合体是可以节省空间的,例如:

我们要搞一个活动,要上线一个礼品兑换单,礼品兑换单中有三种商品 图书、杯子、衬衫 .
每一种商品都有: 库存量、价格、商品类型和商品类型相关的其他信息.
  • 图书:设计、书名、作者、页数.
  • 杯子:设计、品牌.
  • 衬衫:设计、颜色、尺寸、品牌

如果我们使用结构体来描述的话,将会是如下代码 

1.4.3.1:结构体描述
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
struct Gift_List
{
	//库存量
	int _Inventory;
	//价格
	double _Price;
	//商品类型
	int Type_Of_Merchandise;

	//书的特殊属性
	char _Name[20];
	//书的作者
	char _Author[20];
	//书的页数
	int _Pages;

	//衬衫的颜色
	char _Color[20];
	//衬衫的尺寸
	int _Sizes;

	//三者的设计
	char _Desigin[20];
	//三者的品牌
	char _Brand[20];
};

int main()
{
	printf("%zd\n", sizeof(struct Gift_List));
	return 0;
}

  • 上面的结构其实设计的很简单,用起来也方便,但是结构的设计中包含了所有礼品的各种属性,这样使得结构体的大小就会偏大,比较浪费内存.因为对于礼品兑换单中的商品来说,只有部分属性信息是常用的.
  • 比如:商品是图书,就不需要_Design、_Color、_Sizes.
  • 所以可以把公共属性单独写出来,剩余属于各种商品本身的属性使用联合体保存起来,这样就可以节省所需的内存空间,一定程度上节省了内存。
1.4.3.2:使用联合体描述 
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
struct Gift_List
{
	//库存量
	int _Inventory;
	//价格
	double _Price;
	//商品类型
	int Type_Of_Merchandise;
	//三者的设计
	char _Desigin[20];
	//三者的品牌
	char _Brand[20];
	union
	{
		struct Book
		{
			//书的特殊属性
			char _Name[20];
			//书的作者
			char _Author[20];
			//书的页数
			int _Pages;
		};
		struct Shirt
		{
			//衬衫的颜色
			char _Color[20];
			//衬衫的尺寸
			int _Sizes;
		};
	};
};

int main()
{
	printf("Gift_List(嵌套联合体):>%zd\n", sizeof(struct Gift_List));
	return 0;
}

通过对比二者,我们可以清晰地发现,使用联合体可以大大地减少内存空间的占用.

1.5:联合的一个练习

在数据类型在内存的存储方式那篇博客中,我们讲到了大小端的概念.

  • 大端:地址低位存放着数值高位,地址高位存放着数值低位.
  • 小端:地址低位存放着数值低位,地址高位存放着数值高位.

在那里我们通过拿到数值1的最低位并且按位与1来判断来判断程序的大小端

1.5.1:(通过拿数值1的最低位并且按位与1)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
 
int check_sys()
{
	int value = 1;
	return (*(char*)&value & 1);
}
int main()
{
	int result = check_sys();
	if(result == 0)
	{
		printf("大端存储\n");
	}
	else
	{
		printf("小端存储\n");
	}
 
}

 

 

1.5.2:代码2(通过联合体)

除了上面的方式,我们也可以通过联合体的方式来进行求解,联合体的特点是

  • 联合体的成员是共用一块内存空间的,这样一个联合体变量的大小,至少是最大成员的大(因为联合体至少得有能力保存最大的那个成员).
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int Check_sys()
{
	union
	{
		int _i;
		char _c;
	}un;
	un._i = 1;
	return un._c;
}

int main()
{
	int result = Check_sys();
	if (result == 0)
	{
		printf("大端存储\n");
	}
	else
	{
		printf("小端存储\n");
	}

}

2:枚举类型

2.1:枚举类型的声明

枚举顾名思义就是⼀⼀列举, 把可能的取值⼀⼀列举, 比如我们现实生活中:
  • ⼀周的星期一到星期日是有限的7天,可以⼀⼀列举.
  • 性别有:男、女、保密,也可以⼀⼀列举.
  • 月份有12个月,也可以一一列举.
  • 三原色,也是可以意义列举.

2.1.1:代码1 

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>


//星期
enum Day
{
	Monday,
	Tuesday,
	Wednesday,
	Thursday,
	Friday,
	Saturday,
	Sunday
};

//性别
enum Sex
{
	Boy,
	Girl,
	Other
};

//颜色
enum Color
{
	Red,
	Green,
	Blue
};

int main()
{
	printf("Day:Monday> %d\n", Monday);
	printf("Sex:Girl> %d\n", Girl);
	printf("Color:Blue> %d\n", Blue);
	return 0;
}
  •  以上定义的 enum Day,enum Sex,enum Color 都是枚举类型.
  • {}中的内容以,为分隔符,枚举类型的可以取值,也叫枚举常量.
  • 这些可能取值都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值.

2.1.2:代码2(给枚举类型赋初值)

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>


//星期
enum Day
{
	Monday = 1,
	Tuesday,
	Wednesday,
	Thursday,
	Friday,
	Saturday,
	Sunday
};

//性别
enum Sex
{
	Boy = 5,
	Girl,
	Other
};

//颜色
enum Color
{
	Red,
	Green,
	Blue = 2
};

int main()
{
	printf("Day:Monday> %d\n", Monday);
	printf("Sex:Girl> %d\n", Girl);
	printf("Color:Blue> %d\n", Blue);
	return 0;
}

2.2:枚举类型的优点

 我们可以使用#define定义常量,但是为什么非要使用枚举呢

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

2.3:枚举类型的使用

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>



//性别
enum Sex
{
	Boy = 5,
	Girl,
	Other
};


int main()
{
	enum Sex Tom = Boy;
	printf("%d\n", Tom);
	return 0;
}

那是否可以拿整数给枚举变量赋值呢?在C语言中是可以的,但是在C++是不行的,C++的类型检查比较较严格。
好啦,uu们,C语言的联合与枚举这部分滴详细内容博主就讲到这里啦,如果uu们觉得博主讲的不错的话,请动动你们滴小手给博主点点赞,你们滴鼓励将成为博主源源不断滴动力,同时也欢迎大家来指正博主滴错误.

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

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

相关文章

前端界面搜索部分,第一个选择框的值,影响第二个选择框的值

1.字段声明 {title: 单位名称,dataIndex: departmentId,align: center,width: 100,hideInTable: true,renderFormItem: (item, { defaultRender, ...rest }) > (<ProFormSelectname"departmentId"// label"单位名称"options{hospitaltData}onChange…

旋转矩阵乘法,自动驾驶中的点及坐标系变换推导

目录 1. 矩阵乘法的内项相消 2. 左右乘&#xff0c;内外旋与动静坐标系 3. 点变换 3.1 点旋转后的点坐标表示 3.2 坐标系旋转后的点坐标表示 4. 坐标变换的实质 1. 矩阵乘法的内项相消 关于旋转变换&#xff0c;离不开矩阵的乘法&#xff0c;而矩阵乘法的物理意义和本身数…

电脑usb控制软件有哪些?6款软件帮你轻松解决USB端口泄密烦恼!

在数字化时代&#xff0c;企业的信息安全成为重中之重。 然而&#xff0c;USB端口泄密事件频发&#xff0c;给企业的数据安全和业务连续性带来了巨大威胁。 此前&#xff0c;某大型制造企业&#xff0c;由于员工在日常工作中频繁使用U盘等USB存储设备&#xff0c;导致公司核心…

[Linux]自定义shell详解

自定义shell 前言1.命令行提示符&#xff0c;字符串的打印1.1命令行提示符2.命令行字符串 2.0对命令行字符串进行切割2.执行命令3.有趣的小问题完整代码 前言 写之前我们先看看一个完整的shell都包括了什么 $符号前面&#xff08;包括这个符号&#xff09;就是命令行提示符&a…

电线电缆制造5G智能工厂物联数字孪生平台,推进制造业数字化转型

电线电缆制造行业作为关键的基础设施建设领域&#xff0c;正积极拥抱新技术&#xff0c;推动生产方式的深刻变革。电线电缆制造5G智能工厂物联数字孪生平台的兴起&#xff0c;不仅为行业注入了新的活力&#xff0c;更为制造业的数字化转型树立了新的标杆。 电线电缆制造5G智能…

【项目案例】物联网比较好的10+练手项目推荐,附项目文档/源码/视频

练手项目推荐 1 智能小车 项目功能介绍&#xff1a; 本项目由三部分组成&#xff1a;应用端&#xff08;微信小程序&#xff09;、设备端&#xff08;Hi3861&#xff09;、驱动端&#xff08;UPS&#xff09;。 1. 应用端&#xff0c;采用微信小程序作为应用端控制界面。在开…

8个4K图片壁纸网站分享

整理了8个精选的图片壁纸网站&#xff0c;它们提供了丰富多样的壁纸选择&#xff0c;从自然风光到艺术创作&#xff0c;应有尽有。准备好让你的设备焕然一新了吗&#xff1f;让我们一起来看看这些壁纸宝藏吧&#xff01; 1、菜鸟图库 美女图片|手机壁纸|风景图片大全|高清图片…

工业交换机如何保证数据的访问安全

在现代工业自动化环境中&#xff0c;工业交换机作为关键的网络设备&#xff0c;扮演着数据传输和信息交互的重要角色。为了确保数据的访问安全&#xff0c;工业交换机不仅具备高效的转发性能&#xff0c;还集成了多层次的安全防护机制&#xff0c;以抵御各种潜在的网络威胁。 首…

Unity之FPS

目录 &#x1f3ae;MouseLook摄像机旋转脚本 &#x1f3ae;PickUpItem武器拾取脚本 &#x1f3ae;PlayerController玩家控制器 &#x1f3ae;Inventory武器库 &#x1f3ae;Weapon武器抽象类 &#x1f3ae;Weapon_AutomaticGun武器脚本 其实这个教程很早就收藏了就是被20…

MySQL之表内容的增删改查(含oracel 9i经典测试雇佣表下载)

目录 一:Create 二:Retrieve 1.select列 2.where条件 3.结果排序 4. 筛选分页结果 三:Update 四:Delete 1.删除数据 2. 截断表 五&#xff1a;插入查询结果 六&#xff1a;聚合函数 七:group by子句的使用 表内容的CRUD操作 : Create(创建), Retrieve(读取)…

助力企业降低成本,ByteHouse打造新一代“弹性”云数仓

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 在当今的互联网应用中&#xff0c;业务流量往往具有很大的不确定性。 例如&#xff0c;电商平台在 “618”“双 11” 等促销活动期间&#xff0c;访问量会呈爆发式增…

计算机毕业论文题目之基于Web技术B/S结构的新生管理系统包含报道,寝室宿舍,缴费学费,数据统计分析汇总等功能的源代码下载

为了满足功能需求&#xff0c;我们将设计并实现一个基于Web技术的B/S架构下的新生管理系统。本系统旨在通过前端与后端分离的设计模式&#xff0c;为用户提供简洁、高效的交互体验&#xff0c;并确保数据的安全性和系统的可扩展性。下面将从系统架构、功能模块以及技术选型三个…

LeetCode[中等] 142. 环形链表 II

给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整…

SwiftData 共享数据库在 App 中的改变无法被 Widgets 感知的原因和解决

0. 问题现象 我们 watchOS 中的 App 和 Widgets 共享同一个 SwiftData 底层数据库&#xff0c;但是在 App 中对数据库所做的更改并不能被 Widgets 所感知。换句话说&#xff0c;App 更新了数据但在 Widgets 中却看不到。 如上图所示&#xff1a;我们的 App 在切换至后台之前会…

你是不是分不清哪些字体是商用,哪些非商用?快来看,免得莫名其妙负债。

前言 最近发现有好多小伙伴在做PPT的时候&#xff0c;都有一个很不好的习惯&#xff1a;没有调整好字体。 这里说的没有调整好字体的意思是&#xff1a;在一些公开发布的内容上使用一些可能造成侵权的字体。 字体侵权‌的后果相当严重。轻者可能面临法律纠纷&#xff0c;重者…

软件开发团队时间管理的5大技巧

软件开发团队运用时间管理技巧&#xff0c;有助于提升项目效率&#xff0c;确保任务按时完成&#xff0c;减少资源浪费&#xff0c;节约开发时间&#xff0c;增强团队协作&#xff0c;最终有利于项目成功交付。如果开发团队不采取时间管理技巧&#xff0c;可能导致项目延期、资…

如何搭建客户服务知识库?五项基本方法让你业务增长100%

在竞争激烈的市场环境中&#xff0c;优质的客户服务已成为企业脱颖而出的关键。而一个高效、全面的客户服务知识库&#xff0c;不仅能够提升客户满意度&#xff0c;还能显著降低客服团队的工作负担&#xff0c;促进业务的稳健增长。本文将介绍五项基本方法&#xff0c;帮助你搭…

SpringBoot Admin调整类的日志级别

进入 SpringBoot Admin &#xff0c;通过服务名称&#xff0c; 找到服务后。 点击 “日志” – “日志配置” &#xff0c;输入类名&#xff0c;即可调整 这个类的日志级别。

Python模块和包:标准库模块(os, sys, datetime, math等)②

文章目录 一、os 模块1.1 获取当前工作目录1.2 列出目录内容1.3 创建和删除目录1.4 文件和目录操作 二、sys 模块2.1 获取命令行参数2.2 退出程序2.3 获取 Python 版本信息 三、datetime 模块3.1 获取当前日期和时间3.2 日期和时间的格式化3.3 日期和时间的运算 四、math 模块4…

.NET常见的几种项目架构模式,你知道几种?

前言 项目架构模式在软件开发中扮演着至关重要的角色&#xff0c;它们为开发者提供了一套组织和管理代码的指导原则&#xff0c;以提高软件的可维护性、可扩展性、可重用性和可测试性。 假如你有其他的项目架构模式推荐&#xff0c;欢迎在文末留言&#x1f91e;&#xff01;&am…