C生万物 | 聊聊枚举与联合体的用法

这篇具有很好参考价值的文章主要介绍了C生万物 | 聊聊枚举与联合体的用法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C生万物 | 聊聊枚举与联合体的用法

C生万物 | 聊聊枚举与联合体的用法

本文,我们就来谈谈C语言中的枚举和联合体,因为这两块知识点比较类似,所以放在一起讲解,不过在此之前你可以先了解一下结构体的相关知识

枚举

1、枚举类型的定义

对于枚举,顾名思义就是一一列举,把一个事物可能的取值一一地列举出来

  • 例如在我们现实生活中一周的星期一到星期日是有限的7天,可以一一列举
//星期
enum Day{
	Mon,	
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};
  • 性别有:男、女、保密,也可以一一列举
enum Sex{
	MALE,
	FEMALE,
	SECRET
};
  • 有很多的颜色,也可以一一列举
enum Color{
	RED = 3,	
	GREEN,		
	BLUE
};

以上定义的 enum Dayenum Sexenum Color 都是枚举类型。{}中的内容是枚举类型的可能取值,也叫 【枚举常量】

  • 要怎么证明它是一个常量呢?我们可以试着去修改以下里面的这个值,编译一下就可以发现这个MALE是不可以修改的

C生万物 | 聊聊枚举与联合体的用法

  • 虽然说这个常量是不可改变的,但是对于一个常量在一开始也是需要有一个值,即我们所说的【初始值】,对于定义在枚举内部的常量,是存在初始值的,默认从0开始,依次递增1
  • 我们可以去打印来观察一下是否存在上面这样的规律💻

C生万物 | 聊聊枚举与联合体的用法

  • 当然,我们也可以自己去做赋值

C生万物 | 聊聊枚举与联合体的用法

  • 除此之外,枚举内部的这个值是会自动增长的,假如我们给RED设了一个初始值为3,那么GREEN和BLUE的初始值便会去进行一个自动的增长的,如下所示↓

C生万物 | 聊聊枚举与联合体的用法

2、枚举的使用

那这个枚举定义出来后,要怎么去使用它呢?

  • 其实这和我们在使用结构体的时候是类似的,不过这边记得要去做一个初始化,否则会爆出一个Warning

C生万物 | 聊聊枚举与联合体的用法

  • 但是在初始化的时候,我们不可以像下面这样去初始化,虽然在VS上进行编译是没问题的,但是在其他平台上的话就不一定了。因为这里的3是一个整型,但左侧的c2却是枚举类型,两个类型是不一样的,所以不可以这样去做一个初始化
    👉只能拿枚举常量给枚举变量赋值,才不会出现类型的差异

C生万物 | 聊聊枚举与联合体的用法


当然,枚举还有其他很多的使用场景,例如说你想要将一些相同类型含义的名词包在一块,就可以使用枚举,这里举一个例子:

  • 还记得我们前面学习过的《通讯录》吗,在进行各个功能选择的时候,我们使用到了switch...case语句,例如:使用【1】来代表Add,使用【2】来代表Del,使用【3】来代表Search等等,所以我们还需要去写一个menu菜单,在选择的时候看着菜单才可以进行选择

C生万物 | 聊聊枚举与联合体的用法

  • 那现在在学习了枚举后,你是否可以对其做一个改善呢?此时我们就可以去定义像下面这样的一个枚举类型的 Option
enum Option {
	EXIT,	//0
	ADD,	//1
	DEL,	//2
	SEARCH,
	MODIFY,
	SHOW,
	SORT,
	CLS
};
  • 那么此时我们的case语句就可以写成下面这样了,因为枚举变量的值是会进行自动增长的,刚好对应了我们上面的这些值,这便是枚举的实际应用

C生万物 | 聊聊枚举与联合体的用法

3、枚举的优点

那为什么要使用枚举呢?它有什么优势所在吗?

1、增加代码的可读性和可维护性

  • 这点看上面所讲的通讯录就可以了,上面说到我们一开始在用1,2,3这些数字的时候,很难记住通讯录所有的功能,但是讲这些功能定义成枚举之后,使用像:ADD、DEL…这些来作为通讯录功能的代称时,让别人在阅读你代码的时候就提高了可读性

2、和#define定义的标识符比较枚举有类型检查,更加严谨。

  • 例如说我在这里使用#define去定义了一个MALE2,它的值是6,之前我们在讲这个预处理的时候,有说到过宏是没有类型的,所以编译器在编译的过程中就不会对这个MALE2做类型检查,而是在预处理阶段就直接替换了
  • 但是呢,对于枚举变量来说,它是有类型的,即为enum,所以若是你在定义的过程中出现什么语法错误的话就会直接报错,显得就比较严谨
#define MALE2 6

enum Sex{
	MALE = 1,	// 枚举变量可以赋值
	FEMALE = 2,
	SECRET = 4
};

3、防止了命名污染(封装)

  • 对枚举来说,它将类型相同的常量放在了一起,就不会造成命名冲突了,有关命名空间这一块的话可以看看 C++中的namespace 和 C++中类和对象的封装 ,即将一些内容给做了包装,这样就不会造成一个冲突了,此处便不细讲

4、便于调试

  • 对于枚举来说,还有一个很大的特点就是便于调试,在程序环境和预处理中我们有讲到对于【宏】来说是无法进行调试的,因为在预处理阶段就直接进行替换了,是无法进行调试的
  • 可以观察到,当我去进行调试的时候,在【监视窗口】中是可以看到它们的值的,但是呢在按F11的时候无法进入,而是直接将MAX的值进行了一个替换,所以宏是无法进行调试的

C生万物 | 聊聊枚举与联合体的用法

5、使用方便,一次可以定义多个常量

  • 还记得我们上面定义的一个枚举Day吗,里面存放了从周一到周日七个枚举常量,但若是我们不使用枚举的话,而是用#define去进行定义的话,就需要写7行,虽然看上去很整齐美观,但是在写的时候却没有枚举来得方便
#define MON 1
#define TUE 2
#define WED 3
#define TUS 4
#define FRI 5
#define SAT 6
#define SUN 7

💬 对于枚举的话,就说上面这些了,知识点并不是很多,同学们可以在日常做项目的时候去慢慢体会,枚举这个东西,要看大家自己去悟,当你用多了,也就觉得它并不是一无是处

联合体

1、联合体类型的定义

联合也是一种特殊的自定义类型。这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)。

  • 以下就是一个联合体的声明,通过观察它的形式可以发现其与结构体和枚举非常类似,尤其是和【结构体】,里面可以存放不同的数值类型
// 联合类型的声明
union Un
{
	char c;
	int i;
};
  • 在声明完后去进行定义也是类似的样子
//联合变量的定义
union Un un;

2、联合体的特点

难道联合体就没有其独有的特征吗?

  • 这个当然不会,既然它被称作是联合体(公用体),那一定是可以存在公用一些什么东西的,我们可以去打印其中的变量、地址来观察一下

C生万物 | 聊聊枚举与联合体的用法

  • 于是就有了新的发现,无论是对于这个联合体本身还是其内部成员,它们都使用同一块内存地址
  • 我们可以通过画图的方式来观察一下,通过sizeof(un)可以看到这个联合体在内存中所占的字节数为4,当然为什么为4,后面在谈到【联合体的计算】时我们再去细细地讲一讲这块

C生万物 | 聊聊枚举与联合体的用法

  • 因为在联合体内部,有char类型的变量c和int类型的变量i,前者占1个字节,后者占4个字节,此时变量【c】就是从[0122F928]这块地址开始放置,总共的话就占一个字节。那既然编译器为联合体un就分配了4个字节的空间,而且变量【i】也是从[0122F928]这块地址开始放置,总共也就占这4个字节
  • 那其实就很清晰可以看出:对于联合体内部的成员都是共用一块地址空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)

所以这就可以解释得通为何这个联合体的大小是4了,因为在联合体中成员i是int类型的,其所占的字节数是里面最多的为4个字节

  • 可能这不是很好理解,举个栗子🌰比方说一张大床可以睡两个人,你和你哥哥睡同一张床,那么这张床的大小就取决于你们当中身体面积最大的那个人,若是你哥哥重200斤,那总不能让他睡一个像大学宿舍那样的小床吧,至少是一个1米5的床板才行

C生万物 | 聊聊枚举与联合体的用法

3、联合体大小的计算

规则:

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

  • 我们这里可以做两道题来练习一下,你可以说出下面这个联合体u1的大小吗
union Un1
{
	char c[5];
	int i;
};

int main(void)
{
	printf("%zu\n", sizeof(union Un1));
	return 0;
}
  • 通过观察可以发现,联合体U1中有一个大小为5的字符数组,那么其在内存中就需要占5个字节的大小,那对于变量i来说就需要占4个字节的大小,但为什么最后打印出来的结果是【8】呢?

C生万物 | 聊聊枚举与联合体的用法

  • 这就要去考虑内存对齐了,如果没有这一块基础的话可以去看看 校招热门考点 —— 结构体内存对齐
  • 很简单,字符数组c中的每一个元素在内存中所占大小为1个字节,VS默认对齐数为8,即为1;成员【i】在内存中所占大小为4个字节,VS默认对齐数为8,即为4;因为现在已经存放了5个字节的大小,我们要对齐到最大对齐数的整数倍,即为【8】,因此最后计算出来的联合体的大小就为8

我们趁热打铁,再来看一道。你可试着自己算算看✍

union Un2
{
	short c[7];		// 14
				// 2/8 = 2
	int i;		// 4/8 = 4
};

来分析一下:

  • 联合体内部有一个大小为7的short类型数组,在内存中所占大小为14,整型变量i即为4,那它的大小是多少呢?c数组中的元素个数所占大小为2B,和8一比即为2,i类似,因为现在已经存放了14个字节的大小,我们要对齐到最大对齐数的整数倍,即为【16】,因此最后计算出来的联合体的大小就为16

C生万物 | 聊聊枚举与联合体的用法

直击校招

接下去给大家分享一下在校招的过程中可能会遇到的题目

一道字节校招笔试题

  • 首先我们来看一道笔试题,这是2015年字节的一道笔试题,比较经典,也蛮综合。所以放在这里讲解一下

在X86下,小端字节序存储,有下列程序

#include <stdio.h>
int main()
{
	union
	{
		short k;	// 2/4 = 2
		char i[2];	// 1/4 = 1
		// 大小:2
	}*s, a;
	s = &a;
	s->i[0] = 0x39;
	s->i[1] = 0x38;
	printf("%x\n", a.k);
	return 0;
}

输出结果是( A

A.3839
B.3938
C.380039
D.不确定

【解析】:

  • 首先看到这里有一个联合体,里面有两个成员,那此时我们可以通过上面所学习的【联合体】的知识,首先去算出这个联合体的大小为2字节,对于2字节来说有16个二进制位,即可以表示4个十六进制位,那么此时我们就可以先排除选项CD
  • 接下去就要分析结果是多少,首先我们看到为这个联合体成员数组i进行了赋值,那么此时在内存中这个数组的存放便是3938,但是不要忘了题目中明确给出这是在【小端字节序】中进行存储,所以内存中的低位要放到数值位中的低位,内存中的高位要放到数值位中的高位,此时我们在显示器上看到的数值位便是3839

C生万物 | 聊聊枚举与联合体的用法

  • 不过呢这里打印的是a.k,我们上面所操作的是数组,但是不要忘了这个数组是在联合体内部的,对于联合体来说最大的一个特征就是【所有成员共享同一块空间】,那么此时k的值也发生了变化,因此我们去打印k的值就相当于是在打印数组的值,最后的结果即为[3839]

C生万物 | 聊聊枚举与联合体的用法

一道经典面试题:判断当前计算机的大小端存储

在学习了联合体的相关只是后,我们来做一道面试题:判断当前计算机的大小端存储

  • 这到题其实我们在讲大小端存储的时候已经有讲到过了,还记得解题思路吗?根据大小端存储的特性:
    • 【大端存储模式】:是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
    • 【小端存储模式】:是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地址中;
  • 所以我们在判断当前机器是大/小端字节的时候,只需要去判断这个数的地址的第一位是1还是0即可,这里就不细讲了,如果不太清楚同学可以去学习一下
int check_sys(int num)
{
	char* p = (char*)&num;
	if (*p == 1) {
		return 1;
	}
	else {
		return 0;
	}
}

不过在学习了【联合体】之后,你是否可以使用它来进行实现呢?

  • 在此我封装了一个函数,里面呢声明了一个匿名联合体(和匿名结构体一样没有名称),然后在声明的同时直接定义了一个联合体un,将里面的成员【i】赋值为1,然后再返回成员【c】
int check_sys() {
	union {
		char c;
		int i;
	}un;
	un.i = 1;
	return un.c;
}
  • 可能有同学会疑惑最后的这两步到底在干嘛🤔 此时就需要我们前面所学习的联合体的特点了,因为联合体中的成员是共用一块内存空间的,所以给成员【i】进行赋值后,其使用二进制进行表示即为00 00 00 01,那么根据VS小端存放,当前内存地址中所存放的即为01 00 00 00,我们可以打开内存来观察一下💻

C生万物 | 聊聊枚举与联合体的用法

  • 那么此时联合体中的成员c便为0x00EFF99C这块地址上的第一个字节即01,这个时候我们去return un.c的时候就是把这个01给返回回去了,使用int整型来接受即为1,所以最后打印的结果就是【小端】

C生万物 | 聊聊枚举与联合体的用法
💬 这道经典面试题你学会(废)︿( ̄︶ ̄)︿了吗?

总结与提炼

最后来总结一下本文所学习的内容📖

  • 首先我们学习了有关【枚举enum】的相关知识:知道了可以将多个常量封装在一起,来替代繁琐的【宏定义】,在使用这些枚举常量的时候不仅可以增加代码的阅读性,而且还可以方便去进行调试,如此好的东西,还不赶紧用起来~
  • 接下去呢我们又学习了有关【联合体union】的相关知识:知道了原来多个类型的成员可以存放在同一块地址中,共用同一个地址,我们还利用这特性去解决了一道面试呢,还有印象吗~

C生万物 | 聊聊枚举与联合体的用法

C生万物 | 聊聊枚举与联合体的用法文章来源地址https://www.toymoban.com/news/detail-501472.html

到了这里,关于C生万物 | 聊聊枚举与联合体的用法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 详解自定义类型:枚举与联合体!

    目录  ​编辑 一、枚举类型 1.枚举类型的声明 2.枚举类型的优点 3.枚举类型的使用 二、联合体类型(共用体) 1.联合体类型的声明 2.联合体的特点 3.相同成员的结构体和联合体的对比 4.联合体大小的计算 5.用联合体判断大小端   三.完结散花                            

    2024年02月19日
    浏览(32)
  • C语言枚举与联合体详解

        本篇文章带来 枚举与联合体 相关知识详细讲解! 如果您觉得文章不错,期待你的一键三连哦,你的鼓励是我创作的动力之源,让我们一起加油,一起奔跑,让我们顶峰相见!!! 目录 一.枚举 1.什么是枚举? 2.枚举类型的定义 3.枚举的优点 4.枚举的使用 二.联合体(共

    2024年02月15日
    浏览(44)
  • 自定义类型:结构体、枚举、联合体

    结构体是一种自定义的数据类型,它由多个不同类型的成员变量组成,结构体可以将多个相关的数据打包在一起,方便进行管理和处理。 定义形式: struct 结构体名{ 类型 成员名1; 类型 成员名2; //更多的成员变量 }; 如描述一个学生: struct Stu这样就和int类型一样,都是数

    2024年02月16日
    浏览(42)
  • 【C语言】自定义类型——枚举、联合体

    对枚举、联合体进行介绍,包括枚举的声明、枚举的优点,联合体的声明、联合体的大小。                  ✨  猪巴戒 :个人主页✨                 所属专栏 :《C语言进阶》         🎈 跟着猪巴戒 ,一起学习C语言🎈 目录 引言 枚举 枚举的优点 联合(共用体

    2024年02月04日
    浏览(46)
  • 【C语言】位段,枚举和联合体详解

      目录 1.位段 1.1 什么是位段 1.2 位段的内存分配 1.3 位段的跨平台问题 2.枚举 2.1 枚举类型的定义 2.2 枚举的优点 3. 联合(共用体) 3.1 联合类型的定义 3.2 联合的特点 3.3 联合大小的计算 位段的声明和结构体是类似的,有两个不同: 1.位段的成员必须是 int、unsigned int 或 sig

    2024年02月11日
    浏览(38)
  • C语言 联合体验证 主机字节序 +枚举

    枚举(Enumeration)是一种在编程语言中表示一组具名 常量 的数据类型。 枚举常常用于定义一组相关的离散值,比如颜色、星期几、月份等。 爱编程的大丙

    2024年02月04日
    浏览(39)
  • C语言中的联合体和枚举

           联合体的是union 除了和结构体不一样之外,联合体的创建语法形式和结构体的很相似,如果不熟悉结构体的创建,可以看一下我上一篇的博客关于结构体知识的详解。        联合体的成员是共用一块内存空间的,这也就是意味着它更节省空间,那也就

    2024年04月10日
    浏览(57)
  • C语言从入门到实战——联合体和枚举

    C语言中,联合体(union)是一种特殊的数据类型,允许存储不同类型的数据在同一块内存空间中。联合体的大小取决于其中最大的成员的大小,共享同一块内存空间的成员可以存储不同类型的数据。 联合体的定义方式与结构体类似,使用 union ,后跟联合体的名称。联

    2024年01月17日
    浏览(41)
  • c语言->自定义类型联合体和枚举类型

    文章目录 ✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:橘橙黄又青_C语言,函数,指针-CSDN博客 目的:学习联合体和枚举类型的声明联合体的特点和大小,枚举类型的有点和使用。 像结构体⼀样,联合体也是由⼀个或者多个成员构

    2024年02月05日
    浏览(35)
  • C语言——自定义类型详解[结构体][枚举][联合体]

    我打算把结构体、枚举、联合体的重点内容总结一下,方便后期复习的时候能够更快,更准确的去拾取遗忘的知识。也希望能给大家起到借鉴的作用,不足的地方,请多多包涵。(不足的地方,也希望大家能够指出来) 结构体是一些值的集合,这些集合称为成员变量,结构体

    2024年02月13日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包