当前位置: 首页 > news >正文

【C语言进阶】枚举和联合

目录

1.枚举

1.1 枚举的优点 

2. 联合(共用体)

2.1 联合体的大小计算

1.枚举

        顾名思义一一列举。例如生活中:一周的七天、性别的男女、月份的12个月等等。这些值都是可以穷举的,那么就可以使用枚举。枚举类型中包含枚举常量,每一个枚举常量其实就是一个数值;从0开始依次递增1。

如果想要从1开始递增的话,我们可以人为地在第一个Mon中赋值为1; 

        枚举跟结构体一样,只是类型,当我们真正创建变量的时候才会在内存中开辟空间;如下图:

1.1 枚举的优点 

        我们可以使用define来定义常量,那么我们为什么要使用枚举来定义常量呢?

①增加代码的可读性和可维护性。

讲到这里,我们之前写过的结构体练习:通讯录中有这么一段代码:当执行到swich语句的时候,我们如何能够确定具体的分支例如case 1是代表着什么呢?

我们可以使用枚举来代替其中的常量,这样一来代码就有很高的可读性了。

② 枚举是有类型的,在c语言中对于类型的检测不够严谨,在cpp中如果你给枚举变量赋于其他的值,那么在编译的时候就会报错:

③ 防止命名污染(封装)。

④便于调试。#define在编译之前做预处理的时候直接替换相应的值,我们可以看见在调试的时候是在预处理的后面,也就是说这里是直接看不到宏定义的,只能看到被宏定义替换的常量。

但是枚举不同 ,枚举不是单纯的替换,在调试代码的时候能够看到相应的枚举类型。

2. 联合(共用体)

        联合也是自定义类型,这种类型定义的变量也包含一系列的成员,这些成员共用同一块空间。下面的例子,char类型占用一个字节,int类型占用4个字节,所以创建的变量至少得5个字节,但是输出了4个字节,这是为什么呢?

        共用体的精髓就在这里 ,我们将结构体变量以及结构体变量的成员进行地址的打印,发现这三个地址是一样的。

         u的地址和a的地址相同很好理解,那么c的地址和a的地址相同说明,至少在第一个字节中他们存放的数据空间是重合的。

        这里可以理解为合租和独立房间的区别,如果是结构体的内存,每一个变量不仅有单独的空间,还有“公摊”面积(浪费的空间);对于联合体,多个变量共用一个空间,类似于合租。

        联合体最巧妙的用法是,当联合体内的变量不是同时要用,那么联合体的优势就体现出来了,例如上图,如果用c的时候,只会占用一个字节,如果用a的时候就会用4个字节。

        所以联合体至少有能力保存最大的那个成员。

        在内存中我们可以清晰地看见,在第一个字节处存的是c,再后三个字节处存的是a。

 先看一个我们曾经写过判断系统大小端的代码,底层逻辑是内存的存储。

int check_sys() 
{int a = 1;return *(char*) & a;// 小端 0x 01 00 00 00// 大端 0x 00 00 00 01
}int main() 
{if (check_sys()) {printf("小端");}else {printf("大端");}
}

 我们可以用共用体来改写一下这个代码:

int check_sys_union()
{union Un{char i;int j;}u;u.j = 1;return u.i;
}int main() 
{if (check_sys()) {printf("小端");}else {printf("大端");}
}

        这两个代码的底层逻辑都是先让整型存储1,占用4个字节,这时候只需要取出第一个字节,判断第一个字节究竟存的是什么即可,共用体利用了先天的优势,直接可以读取第一个字节的内容,如果不用 共用体,我们得强制类型转换才能获得第一个字节。

共同体和结构体一样,如果只是在函数内部使用一次,那么就可以匿名,写法雷同于结构体;

union 
{char i;int j;
}u;

2.1 联合体的大小计算

        一般情况下是选择联合体内较大的那个元素类型的大小,下面这种情况需要内存对齐:

一个char数组的对齐数是char也就是1,int的对齐数是4,最大对齐数是4,所以整体需要4的倍数个字节,如果是4就存不下第一个数组,所以是8;

判断下列的共用体的大小:

①short的对齐数是2;int的对齐数是4,;

②所以整体必须是4的倍数,2 * 7 = 14个字节,足够存下i了,又要满足是4的倍数,所以是16个字节。 

http://www.dtcms.com/a/291844.html

相关文章:

  • thinkbook14+指针消失的解决方法 + Windows常见快捷键
  • 四大组件:ContentProvider学习
  • linux用户态各定时器抖动测试
  • java day16
  • Vue开发常用
  • rk平台(rv1126/rk3588)音视频-交叉编译FFmpeg7.1
  • 如何迁移jenkins至另一台服务器
  • 服务器无法访问公网的原因及解决方案
  • 简单了解下npm、yarn 和 pnpm 中 add 与 install(i) 命令的区别(附上两图带你一目明了)
  • nodejs的npm
  • 技术与情感交织的一生 (十)
  • 最新基于R语言结构方程模型分析与实践技术应用
  • Apache Ignite 的 SQL 功能和分布式查询机制
  • Apache Ignite 中事务的使用方式和机制
  • 短剧小程序系统开发:重塑影视内容传播格局
  • LIMO:仅需817样本激活大模型数学推理能力,挑战“数据规模至上”传统范式
  • Axios 二次封装
  • PHP中的异常处理与自定义错误页面
  • EasyGBS算法仓:找算法,变成 “点一下” 的事!
  • 使用 Conda 工具链创建 UV 本地虚拟环境全记录——基于《Python 多版本与开发环境治理架构设计》
  • Docker实战:使用Docker部署TeamMapper思维导图工具
  • 推送git问题_查询索引文件——查导致的文件
  • 按键精灵脚本:自动化利刃的双面性 - 从技术原理到深度实践与反思
  • windows10安装node-v18.18.0-x64安装
  • async/await 函数
  • 【CVPR 2025】低光增强RT-X Net( 红外辅助结构引导)--part1论文精读
  • 开发者的AI认知指南:用大模型重新理解人工智能(下)
  • 公交车客流人数统计管理解决方案:智能化技术与高效运营实践
  • 九鼎X8390 开发板 联发科 MT8390 / MT8370 芯片平台
  • 华为高斯Gauss数据库版本与兼容协议--详解(附带Gorm连接示例代码)