没有联合和枚举 , C语言怎么能在江湖混 ?

news2024/9/23 11:26:17

本篇会加入个人的所谓‘鱼式疯言’
❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言
而是理解过并总结出来通俗易懂的大白话,
我会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.
🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!!
在这里插入图片描述

前言

在本篇文章中,小编将带领友友们体验联合体和枚举的奥妙之处 😎 😎 😎
下面有请我们今天的主角闪亮登场

目录

1.联合体
2.枚举

一. 联合体

<1>. 联合体类型的概念

union union_name {
   member_type1 member1;
   member_type2 member2;
   ...
};

union_name 是联合体的名称
member_type1、member_type2 是成员的数据类型
member1、member2 是成员的名称

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

<2>. 联合体的特点

第一个特点:

先请宝子们看一段代码 😃 😃 😃
思考一下哦! ! !

#include <stdio.h>
//联合类型的声明
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;
}

在这里插入图片描述

可以很明显的看出他们的地址居然是一模一样哒。

是哒,这就是为什么小编会说,联合体中的成员共同同一块空间了 。
见图也可知晓哦。❤️ ❤️ ❤️
在这里插入图片描述

第二个特点:

老规矩,还是先看代码哦! ! !

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

在这里插入图片描述
我们发现将i的第4个字节的内容修改为55了

就充分体现了给联合体其中一个成员赋值,其他成员的值也跟着变化的特点。

在这里插入图片描述

鱼式疯言

联合体的主要特点用大白话来说就是:

同空间,互影响,可改变。

<3>.联合体大小

重要的提前说

• 联合的大小至少是最大成员的大小。

• 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

证明过程如下

#include <stdio.h>
union Un1
{
	int i;
	char c;

};
union Un2
{
	short c[7];
	int i;
};
int main()
{
	//下面输出的结果是什么?
	printf("%d\n", sizeof(union Un1));
	printf("%d\n", sizeof(union Un2));
	return 0;
}

在这里插入图片描述

在这里插入图片描述

联合体的大小又谁决定,肯定是由最大的那块数据类型决定,

但我们前提是的至少哦

如果超过了怎么办,我们就必须想结构体一样,利用内存对齐来分配我们的空间大小。

什么! ! !
小爱同学说没有看过我写的结构体内存对齐
那小编就把对应标题链接粘贴在这帮助各位友友一起理解哦 💖 💖 💖
《来 ! 来 ! 来 ! 瞧瞧伏地魔大哥是怎么看C语言结构体的 ! ! !》 http://t.csdnimg.cn/XL9n2

鱼式疯言

最大成员是对齐数的整数倍时,整体就是最大内存

不是的话,就要和结构体对齐一样办,整体内存就是对齐后的内存

是不是有小伙伴就疑惑了,我们结构体和联合体的区别在哪呢 🤔 🤔 🤔

好学的友友们请看下个小标题哦,精彩马上呈现 💖 💖 💖

<4>. 联合体与结构体的对比

#include<stdio.h>
//定义结构体类型
struct S
{
	char c;
	int i;
};

//定义联合体类型
union Un
{
	char c;
	int i;
};

int main()
{
	//计算各种大小
	printf("%zd\n", sizeof(struct S));
	printf("%zd\n", sizeof(union Un));
	
	return 0;
}

在这里插入图片描述
在这里插入图片描述
有图有真相

鱼式疯言

简而言之,言而简之。

我们的结构体成员不会互相影响,但占内存

我们的联合体会互相影响,但不占内存

<5>. 联合体的实际运用

栗子 一:

使用联合体是可以节省空间的,举例:
比如,我们要搞一个活动,要上线一个礼品兑换单,礼品兑换单中有三种商品:图书、杯子、衬衫。
每一种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。
图书:书名、作者、页数
杯子:设计
衬衫:设计、可选颜色、可选尺寸
那我们不耐心思考,直接写出一下结构:

//第一种结构体分布
//定义一个结构体礼物
struct gift_list1
{
	//相同的属性
	//库存量
	int nums;
	//价格
	float prize;
	//商品类型
	char type[20];


	//书名
	char bookname[30];
	//作者
	char autor[20];
	//页数
	int num_book;
	//设计
	char dec[50];
	//颜色
	char color[20];
	//大小
	int sizes;
};

如果我们插入联合体的把不同的结构体属性联合起来就可以节省我们的内存

神奇的代码一:

//第二种插入联合体的结构体分布
//定义一个结构体礼物
struct gift_list2
{
	//相同的属性
	//库存量
	int nums;
	//价格
	float prize;
	//商品类型
	char type[20];
	
	//将不同属性的也联合起来
	union pu
	{

		struct book
		{
			//书名
			char bookname[30];
			//作者
			char autor[20];
			//页数
			int num_book;
		};
		struct cup
		{
			//设计
			char dec[50];
		};
		struct shirt
		{
			//设计
			char dec[50];
			//颜色
			char color[20];
			//大小
			int sizes;
		};
		
	};

};

栗子二:

如何判断大小端存储 ? ? ?
假如小爱同学没学联合体之前,肯定会这样写代码
小编说的是假如哦 😁 😁 😁

//判断大小端存储_test
//指针强转法
int conc1(void)
{
	int a = 1;
	return *(char*)(&a);
}

int main()
{
	int c1 = conc1();
	if (c1==1)
	{
		printf("小端存储\n");
	}
	else
	{
		printf("大端存储\n");
	}
	return 0;
}

在这里插入图片描述
但你今天学了小编写的联合体的介绍,友友们不妨这样写代码吧 💖 💖 💖

//联合体
union MyUnion
{
	int i;
	struct MyStruct
	{
		char s1;
		char s2;
		char s3;
		char s4;
	};
};

//结构体法
int conc2(void)
{
	//00 00 00 01 大端存储
	//01 00 00 00 小端存储
	union MyUnion a = { 0 };
	a.i = 1;

	return a.s1;
}


int main()
{
	int c2 = conc2();
	if (c2==1)
	{
		printf("小端存储\n");
	}
	else
	{
		printf("大端存储\n");
	}
	return 0;
}

在这里插入图片描述

在这里插入图片描述
因为 s1 的全部数据 与 i 的前一个字节数据是一致的
所以我们只需要抽离出对应的 s1 即可

鱼式疯言

从中我们看到的联合体本质是联合不同的内存,从中达到节省空间的良效

同时利用公用同一块内存空间的便利,可以有效抽离每个字节的数据

二. 枚举

<1>.枚举的简介

C语言中,枚举是一种用来定义一组具名整数常量的数据类型。枚举类型定义了一系列的枚举常量,也称为 枚举成员。每个枚举常量都有一个对应的整数值,可以在程序中使用这个整数值来表示相应的枚举常量

enum Weekday {
   MONDAY,    // 0
   TUESDAY,   // 1
   WEDNESDAY, // 2
   THURSDAY,  // 3
   FRIDAY,    // 4
   SATURDAY,  // 5
   SUNDAY     // 6
};

枚举类型的定义使用关键字 “enum”,后面跟着枚举类型的名称,然后是一对花括号 {} ,其中列出枚举常量。每个枚举常量都可以显式地指定一个整数值,如果没有指定,默认从 0 开始递增。

鱼式疯言

从我们的枚举的简介中就可以提炼出很多至关重要的信息

一. 枚举本身是 常量

二. 枚举和结构体,联合体一样都是属于自定义的一种 数据类型

三. 枚举只能常量只能表示的 整数

<2>. 举俩个栗子

栗子 一

//枚举类型的定义
enum MyEnum
{
	one=1,
	two,
	three
};


int main()
{
	int n = 0;
	scanf("%d", &n);
	

	switch (n)
	{

	case one:
		printf("one\n");
		break;
	case two:
		printf("two\n");
		break;	
	case three:
		printf("three\n");
		break;
	}
	return 0;
}

在这里插入图片描述
我们可以用这些枚举常量来替换我们case的整数值,以此来增加代码的可读性

鱼式疯言

枚举常量与普通常量之间可以替换

爱提问的小爱同学就要问了,为啥好像用 #define 宏定义枚举常量也是可以的哦 ! ! !
但我们为啥要用枚举呢,这个问题小爱同学问的很好啊。那我们来试试宏定义的效果如何吧 💕 💕 💕

//宏定义的常量
#define one 1
#define two 2
#define three 3



int main()
{
	int n = 0;
	scanf("%d", &n);
	

	switch (n)
	{

	case one:
		printf("one\n");
		break;
	case two:
		printf("two\n");
		break;	
	case three:
		printf("three\n");
		break;
	}
	return 0;
}

在这里插入图片描述
哇塞,没想到效果一样嘞 😲 😲 😲
小爱同学又有疑问了 ? ? ?

那居然效果一样,我们是该用 宏定义 还是用 枚举

居然我们有 宏定义 了,为啥还需要 枚举 呢?

是不是 枚举 有比 宏定义 更有优势的地方呢 ?

这些问题呢,我们小编都会 一 一 为宝子们解答哦,先别着急哦 💖 💖 💖
友友们先看第二栗子哦

栗子二(c++的环境测试)

//枚举定义
enum MyEnum
{
	one,
	two,
	three
};

int main()
{
	int n = 0;
	scanf("%d", &n);
	
	enum MyEnum e = 2;

	switch (n)
	{

	case one:
		printf("one\n");
		break;
	case two:
		printf("two\n");
		break;	
	case three:
		printf("three\n");
		break;
	}
	return 0;
}

在这里插入图片描述
友友们是不是想为啥会报错呢? ? ?
这时聪明的小爱同学就大胆的说出了他的想法:
因为这是枚举类型不能匹配整型类型,就会报错 😁 😁 😁
小编不得不为小爱同学点赞哦,完全正确

没错小编提过枚举类型是也是 数据类型 哦,如果出现类型不匹配就很有可能出现 警告和报错

鱼式疯言

无论是什么枚举类型,联合体类型,结构体类型,温馨提示下友友们都记得类型同一哦 ❤️ ❤️ ❤️

<3>. 枚举类型的与宏定义的差别

在上面的中我们可以明显的看到,枚举有类型检查吧,我们宏定义是没有的呢。
所以小编总结了一下五点

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

鱼式疯言

总之枚举的使用可谓是优势俱全啊 💖 💖 💖
但小编的想法是

建议友友们相同类型的常量我们更常用枚举

如果是不同类型的常量我们更常用宏定义来解决呢

总结

在本篇文章中,小编主要带着大家理解了

  • 联合体:熟悉了联合体的定义并知晓了实际的使用场景,还有联合体相比于结构体的优势
  • 枚举:熟悉了枚举如何定义,枚举需要注意的哪些点,以及枚举相比于宏定义的优势

如果觉得小编写的还不错的咱可支持三关下,不妥当的咱评论区指正

希望我的文章能给各位家人们带来哪怕一点点的收获就是 小编创作 的最大动力 💖 💖 💖

在这里插入图片描述

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

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

相关文章

代码随想录算法训练营DAY14 | 二叉树 (1)

一、二叉树理论基础 1.存储方式 链式存储&#xff1a; 顺序存储&#xff1a; 2.二叉树标准定义(Java) public class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) { this.val val; }TreeNode(int val, TreeNode left, TreeNode right) {…

带你实现用自己域名打开Tomcat

文章目录 Tomcat1.1、Tomcat 下载1.2、Tomcat 文件图解1.3、 启动或关闭 Tomcat1.3.1、 启动1.3.2、 关闭程序2.1、 修改端口号2.2、修改主机名称Tomcat 1.1、Tomcat 下载 首先去Tomcat 官网下载找到我们需要下载的版本 1.2、To

SpringBoot:多环境配置

多环境配置demo代码&#xff1a;点击查看LearnSpringBoot02 点击查看更多的SpringBoot教程 方式一、多个properties文件配置 注意&#xff1a;创建properties文件,命名规则&#xff1a;application-&#xff08;环境名称&#xff09; 示例&#xff1a;application-dev.proper…

c#cad 创建-点(六)

运行环境 vs2022 c# cad2016 调试成功 一、代码说明 创建一个点的命令方法。代码的主要功能是在当前活动文档中创建一个点&#xff0c;并将其添加到模型空间块表记录中。 代码的主要步骤如下&#xff1a; 获取当前活动文档、数据库和编辑器对象。使用事务开始创建点的过程…

Java设计模式大全:23种常见的设计模式详解(二)

本系列文章简介&#xff1a; 设计模式是在软件开发过程中&#xff0c;经过实践和总结得到的一套解决特定问题的可复用的模板。它是一种在特定情境中经过验证的经验和技巧的集合&#xff0c;可以帮助开发人员设计出高效、可维护、可扩展和可复用的软件系统。设计模式提供了一种在…

Leetcode第123场双周赛

Leetcode第123场双周赛 本人水平有限&#xff0c;只做前三道 一、三角形类型 给你一个下标从 0 开始长度为 3 的整数数组 nums &#xff0c;需要用它们来构造三角形。 如果一个三角形的所有边长度相等&#xff0c;那么这个三角形称为 equilateral 。 如果一个三角形恰好有两…

【lesson11】高并发内存池性能优化

文章目录 高并发内存池性能问题基数树优化性能代码一层基数树两层基数树三层基数树 一层基数树替代mapPageCache.hPageCache.cpp基数树线程安全的原因 高并发内存池性能问题 我们知道&#xff0c;我们实现的高并发内存池存在大量的申请锁和&#xff0c;释放锁&#xff0c;而这…

【RL】Basic Concepts in Reinforcement Learning

Lecture1: Basic Concepts in Reinforcement Learning MDP(Markov Decision Process) Key Elements of MDP Set State: The set of states S \mathcal{S} S&#xff08;状态 S \mathcal{S} S的集合&#xff09; Action: the set of actions A ( s ) \mathcal{A}(s) A(s)…

奚梦瑶何猷君香港共度佳节,幸福全家福彰显深厚亲情。

♥ 为方便您进行讨论和分享&#xff0c;同时也为能带给您不一样的参与感。请您在阅读本文之前&#xff0c;点击一下“关注”&#xff0c;非常感谢您的支持&#xff01; 文 |猴哥聊娱乐 编 辑|徐 婷 校 对|侯欢庭 从奚梦瑶父母与赌王家族的全家福中&#xff0c;我们可感受到两…

图灵之旅--二叉树堆排序

目录 树型结构概念树的表示形式 二叉树概念特殊的二叉树二叉树性质二叉树的存储二叉树的遍历前中后序遍历 优先级队列(堆)概念 优先级队列的模拟实现堆的性质概念堆的存储方式堆的创建 堆常用接口介绍PriorityQueue的特性PriorityQueue常用接口介绍优先级队列的构造插入/删除/获…

【Linux笔记】文件系统与软硬链接

一、文件系统概述 1.1、先来聊一聊“磁盘” 在讲解文件系统之前&#xff0c;我觉得有必要先聊一下“磁盘”&#xff0c;因为我觉得如果弄懂了磁盘的存储原理&#xff0c;大家可能更容易理解文件系统是怎么管理数据的&#xff0c;并且理解计算机是怎么将磁盘抽象到文件系统的。…

SpringBoot多模块项目proguard混淆

SpringBoot多模块项目proguard混淆 前言整活项目目录混淆后的效果图混淆配置混淆配置规则keep相关通配符和关键字keep说明常见问题解决办法效果前言 proguard 是压缩、优化和混淆Java字节码文件的免费的工具。 它可以删除无用的类、字段、方法和属性。可以删除没用的注释,最大…

156基于Matlab的光纤陀螺随机噪声和信号

基于Matlab的光纤陀螺随机噪声和信号&#xff0c;利用固定步长和可调步长的LMS自适应滤波、最小二乘法、滑动均值三种方法进行降噪处理&#xff0c;最后用阿兰方差评价降噪效果。程序已调通&#xff0c;可直接运行。 156 信号处理 自适应滤波 降噪效果评估 (xiaohongshu.com)

【Linux工具篇】调试器gdb

目录 releaseVSdebug模式 使用命令 NO1运行 NO2查看 NO3断点 总结 releaseVSdebug模式 程序的发布方式有两种&#xff0c;debug模式和release模式Linux gcc/g出来的二进制程序&#xff0c;默认是release模式Linux gcc/g要使其debug模式编译&#xff0c;加上-g选项要使用g…

Kuberntes权威指南

一、目录 二、Kubernetes入门 三、Kubernetes核心原理 四、Kubernetes开发指南 五、Kubernetes运维指南 六、Kubernetes高级案例进阶 七、Kubernetes源码导读

【Java程序设计】【C00247】基于Springboot的农机电招平台(有论文)

基于Springboot的农机电招平台&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的农机电招平台 本系统分为系统功能模块、管理员功能模块、农机机主功能模块以及使用者功能模块。 系统功能模块&#xff1a;农机电招…

验证码倒计时:用户界面的小细节,大智慧

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 验证码倒计时&#xff1a;用户界面的小细节&#xff0c;大智慧 前言为什么需要验证码倒计时防止滥用&#xff1a;用户心理&#xff1a; 设计考量可见性&#xff1a;友好性&#xff1a;适应性&#xff…

大数据学习之Redis,十大数据类型的具体应用(五)

目录 3.9 Redis地理空间&#xff08;GEO&#xff09; 简介 原理 Redis在3.2版本以后增加了地理位置的处理哦 命令 命令实操 如何获得某个地址的经纬度 3.9 Redis地理空间&#xff08;GEO&#xff09; 简介 移动互联网时代LBS应用越来越多&#xff0c;交友软件中附近的…

linux、windows 安装 vue-cli

Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统&#xff0c;提供&#xff1a; 通过 vue/cli 实现的交互式的项目脚手架。 通过 vue/cli vue/cli-service-global 实现的零配置原型开发。 一个运行时依赖 (vue/cli-service) 可升级&#xff1b; 基于 webpack 构建&#…

【C++】win11,OpenCV安装教程(VS2022)

1.下载 首先进入官网&#xff0c;下载对应的安装包&#xff0c;苹果系统就选IOS pack&#xff0c;微软系统就选Windows 下载地址&#xff1a;Releases - OpenCV 不方便外网下载的话可以下载我分享的百度网盘资源&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1lV7l…