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

2024-02-06 23:52

本文主要是介绍没有联合和枚举 , C语言怎么能在江湖混 ?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

前言

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

目录

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,    // 0TUESDAY,   // 1WEDNESDAY, // 2THURSDAY,  // 3FRIDAY,    // 4SATURDAY,  // 5SUNDAY     // 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 3int 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. 枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用

鱼式疯言

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

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

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

总结

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

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

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

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

在这里插入图片描述

这篇关于没有联合和枚举 , C语言怎么能在江湖混 ?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/685928

相关文章

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

C语言中的数据类型强制转换

《C语言中的数据类型强制转换》:本文主要介绍C语言中的数据类型强制转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C语言数据类型强制转换自动转换强制转换类型总结C语言数据类型强制转换强制类型转换:是通过类型转换运算来实现的,主要的数据类型转换分为自动转换

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

C语言实现两个变量值交换的三种方式

《C语言实现两个变量值交换的三种方式》两个变量值的交换是编程中最常见的问题之一,以下将介绍三种变量的交换方式,其中第一种方式是最常用也是最实用的,后两种方式一般只在特殊限制下使用,需要的朋友可以参考下... 目录1.使用临时变量(推荐)2.相加和相减的方式(值较大时可能丢失数据)3.按位异或运算1.使用临时

使用C语言实现交换整数的奇数位和偶数位

《使用C语言实现交换整数的奇数位和偶数位》在C语言中,要交换一个整数的二进制位中的奇数位和偶数位,重点需要理解位操作,当我们谈论二进制位的奇数位和偶数位时,我们是指从右到左数的位置,本文给大家介绍了使... 目录一、问题描述二、解决思路三、函数实现四、宏实现五、总结一、问题描述使用C语言代码实现:将一个整

C语言字符函数和字符串函数示例详解

《C语言字符函数和字符串函数示例详解》本文详细介绍了C语言中字符分类函数、字符转换函数及字符串操作函数的使用方法,并通过示例代码展示了如何实现这些功能,通过这些内容,读者可以深入理解并掌握C语言中的字... 目录一、字符分类函数二、字符转换函数三、strlen的使用和模拟实现3.1strlen函数3.2st

Go语言中最便捷的http请求包resty的使用详解

《Go语言中最便捷的http请求包resty的使用详解》go语言虽然自身就有net/http包,但是说实话用起来没那么好用,resty包是go语言中一个非常受欢迎的http请求处理包,下面我们一起来学... 目录安装一、一个简单的get二、带查询参数三、设置请求头、body四、设置表单数据五、处理响应六、超

电脑开机提示krpt.dll丢失怎么解决? krpt.dll文件缺失的多种解决办法

《电脑开机提示krpt.dll丢失怎么解决?krpt.dll文件缺失的多种解决办法》krpt.dll是Windows操作系统中的一个动态链接库文件,它对于系统的正常运行起着重要的作用,本文将详细介绍... 在使用 Windows 操作系统的过程中,用户有时会遇到各种错误提示,其中“找不到 krpt.dll”

C语言中的浮点数存储详解

《C语言中的浮点数存储详解》:本文主要介绍C语言中的浮点数存储详解,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、首先明确一个概念2、接下来,讲解C语言中浮点型数存储的规则2.1、可以将上述公式分为两部分来看2.2、问:十进制小数0.5该如何存储?2.3 浮点

基于Python实现多语言朗读与单词选择测验

《基于Python实现多语言朗读与单词选择测验》在数字化教育日益普及的今天,开发一款能够支持多语言朗读和单词选择测验的程序,对于语言学习者来说无疑是一个巨大的福音,下面我们就来用Python实现一个这... 目录一、项目概述二、环境准备三、实现朗读功能四、实现单词选择测验五、创建图形用户界面六、运行程序七、