C语言自定义类型【联合体与枚举】

2024-04-28 07:36

本文主要是介绍C语言自定义类型【联合体与枚举】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 1.联合体
    • 1.1联合体的声明
    • 1.2联合体的特点
    • 1.3联合体的大小计算
      • 联合体的使用案例
  • 2.枚举
    • 2.1枚举类型的声明
    • 2.2枚举类型的优点(为什么使用枚举)
    • 2.3枚举类型的使用
  • 结语

1.联合体

1.1联合体的声明

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

#include<stdio.h>
//联合体的声明
union Un
{char c1;int i;char c2;
};int main()
{//创建一个union Un类型的临时变量union Un un = { 0 };//计算联合体变量的大小printf("union Un 大小为%zd", sizeof(un));return 0;
}

在这里插入图片描述

为什么是4呢?
我们就来了解联合体的特点吧

1.2联合体的特点

联合的成员是共用同一块内存空间,所以一个联合体变量的大小至少是最大成员的大小(因为联合至少得有能力存放最大的成员)。

#include<stdio.h>
//联合体的声明
union Un
{char c1;int i;
};int main()
{//创建一个union Un类型的临时变量union Un un = { 0 };//查看联合成员的地址printf("成员i 的地址为  %p\n", &un.i);printf("成员c1的地址为  %p\n", &un.c1);printf("联合体un的地址为%p\n", &un.c1);return 0;
}

在这里插入图片描述
可以看到输出的三个地址一模一样。

#include<stdio.h>//联合体的声明
union Un
{char c1;int i;
};int main()
{//创建一个union Un类型的临时变量union Un un = { 0 };un.i = 0x11223344;un.c1 = 0x55;//查看联合体成员的值(16进制)printf("成员i的为%x\n", un.i);return 0;
}

在这里插入图片描述

在这里插入图片描述
我们通过调试可以看到,i的第4个字节的内容被修改为了55。
在这里插入图片描述
在这里插入图片描述
这又证明了,联合体的所有成员是共用同一块空间。

成员相同的结构体和联合体进行比较

#include<stdio.h>struct Str
{char c1;int i1;
};union Un
{char c2;int i2;
};int main()
{printf("struct Str的大小为%zd\n", sizeof(struct Str));printf("union Un的大小为%3zd", sizeof(union Un));return 0;
}

在这里插入图片描述
他们的成员大小相同,成员顺序相同,但输出的结果还是不同,也就是说结构体和联合体对待成员的存放是不同的。
结构体每个成员有独立的空间,而联合体是共用一块空间

1.3联合体的大小计算

1.联合体的大小至少是最大成员的大小
2.如果最大成员的大小不是最大对齐数的整数倍时,空间大小要对齐到最大对齐数的整数倍
看代码:

union Un1//最大对齐数为4(int)
{char ch[5];//大小为5(最大)int i;//大小为4
};union Un2//最大对齐数为4(int)
{short sh[5];//大小为10(最大)int i;//大小为4
};union Un3//最大对齐数为8(long long)
{int arr[5];//大小为20(最大)long long lg;//大小为8
};int main()
{printf("union Un1的大小为%zd\n", sizeof(union Un1));printf("union Un2的大小为%zd\n", sizeof(union Un2));printf("union Un3的大小为%zd\n", sizeof(union Un3));return 0;
}

在这里插入图片描述

联合体的使用案例

联合体的使用案例
假如我们要搞⼀个活动,要上线⼀个礼品兑换单
礼品兑换单中有三种商品:图书、杯⼦、衬衫。
每种商品都有:库存,价格,商品类型,我们称之为公共属性
其中每个商品有各自的特殊属性
图书:书名,作者,页数
杯子:设计方案
衬衫:设计方案,颜色,尺寸

解决方法一:

struct gift_list
{//公共属性int stock_number;//库存double price;//价格int item_type;//商品类型//特殊属性char Title[20];//书名char Author[20];//作者int Num_page;//页数char Design;//设计方案(杯子和衬衫都有设计方案)char Colors[10];//颜色int Size;//尺寸};

上面的的代码,很暴力,也很方便,但是结构的设计中包含了所有礼物的属性,这样会使得结构体的大小会偏大,比较浪费空间。而且对于单个商品来说,只有部分属性是我要用的。

比如商品是衬衫的话我要用的就是Design、Colors、Size,而Title、Author、Num_page就是不需要的属性

所有我们可以把公共属性独立写出来,剩余各种商品本身的特殊属性就可以使用联合体。这样就可以在一定程度上节省空间。

struct Gift_List
{//公共属性int stock_number;//库存double price;//价格int item_type;//商品类型union MyUnion{struct{char Title[20];//书名char Author[20];//作者int Num_page;//页数}book;struct {char Design;//设计方案(杯子和衬衫都有设计方案)}mug;struct {char Design;//设计方案(杯子和衬衫都有设计方案)char Colors[10];//颜色int Size;//尺寸}shirt;}item;
};

2.枚举

2.1枚举类型的声明

顾名思义就是将可能的元素进行一一列举
例如我们生活中的:一周的星期一到星期日、十二个月份、三原色;这些都可以一一列举
附上代码

enum Colors//
{RED,BLUE,GREEN
};enum Week_By_Day
{Mon,Tues,Wed,Thur,Fri,Sat,Sun
};

以上定义的 颜色一周都是枚举类型。
而{}里的内容是枚举类型里的可能取值,这也叫做枚举常量。

这些可能取值都是有值的(创建常量的时候肯定是要赋值的)
枚举常量默认从0开始,依次递增1,当然,在声明枚举类型的时候也可以赋初始值。

enum Direction
{NORTH,//初始值在没有赋值的情况下就是0//后面的值发生改变也不会改变前面的值EAST,WEST = 5,SOUTH
};int main()
{printf("%d\n", NORTH);printf("%d\n", EAST);printf("%d\n", WEST);printf("%d\n", SOUTH);return 0;
}

在这里插入图片描述
初始值在没有赋值的情况下就是0,后面的值发生改变也不会改变前面的值

2.2枚举类型的优点(为什么使用枚举)

明明我们有#define 来定义常量,为什么要使用枚举?

1.增加代码的可读性和可维护性
2.和#define定义的标识符进行比较,枚举有类型检查,更加严谨
3.便于调试,预处理阶段会直接将#define定义的符号替换为原来的符号
4.使用更方便,一次可以定义多个常量
5.枚举常量是遵循作用域规则的,枚举声明在某个函数内,只能在该函数内部使用

2.3枚举类型的使用

#include<stdio.h>
enum Colors
{RED,//0BLUE,//1GREEN//2
};
int main()
{enum Color clr = GREEN;//使⽤枚举常量给枚举变量赋值printf("clr的值为%d", clr);return 0;
}

在这里插入图片描述

补充:
那我们是否可以拿整数给枚举变量赋值呢?在C语言中是可以的,但是在C++是不行的,C++的类型检查比较严格。

结语

最后感谢您能阅读完此片文章,如果有任何建议或纠正欢迎在评论区留言。如果您认为这篇文章对您有所收获,点一个小小的赞就是我创作的巨大动力,谢谢

这篇关于C语言自定义类型【联合体与枚举】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Vite 打包目录结构自定义配置小结

《Vite打包目录结构自定义配置小结》在Vite工程开发中,默认打包后的dist目录资源常集中在asset目录下,不利于资源管理,本文基于Rollup配置原理,本文就来介绍一下通过Vite配置自定义... 目录一、实现原理二、具体配置步骤1. 基础配置文件2. 配置说明(1)js 资源分离(2)非 JS 资

Python中Json和其他类型相互转换的实现示例

《Python中Json和其他类型相互转换的实现示例》本文介绍了在Python中使用json模块实现json数据与dict、object之间的高效转换,包括loads(),load(),dumps()... 项目中经常会用到json格式转为object对象、dict字典格式等。在此做个记录,方便后续用到该方

GO语言短变量声明的实现示例

《GO语言短变量声明的实现示例》在Go语言中,短变量声明是一种简洁的变量声明方式,使用:=运算符,可以自动推断变量类型,下面就来具体介绍一下如何使用,感兴趣的可以了解一下... 目录基本语法功能特点与var的区别适用场景注意事项基本语法variableName := value功能特点1、自动类型推

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

python中的显式声明类型参数使用方式

《python中的显式声明类型参数使用方式》文章探讨了Python3.10+版本中类型注解的使用,指出FastAPI官方示例强调显式声明参数类型,通过|操作符替代Union/Optional,可提升代... 目录背景python函数显式声明的类型汇总基本类型集合类型Optional and Union(py

MySQL中查询和展示LONGBLOB类型数据的技巧总结

《MySQL中查询和展示LONGBLOB类型数据的技巧总结》在MySQL中LONGBLOB是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据,:本文主要介绍MySQL中查询和展示LO... 目录前言1. 查询 LONGBLOB 数据的大小2. 查询并展示 LONGBLOB 数据2.1 转换为十

Go语言连接MySQL数据库执行基本的增删改查

《Go语言连接MySQL数据库执行基本的增删改查》在后端开发中,MySQL是最常用的关系型数据库之一,本文主要为大家详细介绍了如何使用Go连接MySQL数据库并执行基本的增删改查吧... 目录Go语言连接mysql数据库准备工作安装 MySQL 驱动代码实现运行结果注意事项Go语言执行基本的增删改查准备工作

聊聊springboot中如何自定义消息转换器

《聊聊springboot中如何自定义消息转换器》SpringBoot通过HttpMessageConverter处理HTTP数据转换,支持多种媒体类型,接下来通过本文给大家介绍springboot中... 目录核心接口springboot默认提供的转换器如何自定义消息转换器Spring Boot 中的消息

Kotlin 枚举类使用举例

《Kotlin枚举类使用举例》枚举类(EnumClasses)是Kotlin中用于定义固定集合值的特殊类,它表示一组命名的常量,每个枚举常量都是该类的单例实例,接下来通过本文给大家介绍Kotl... 目录一、编程枚举类核心概念二、基础语法与特性1. 基本定义2. 带参数的枚举3. 实现接口4. 内置属性三、

Go语言使用Gin处理路由参数和查询参数

《Go语言使用Gin处理路由参数和查询参数》在WebAPI开发中,处理路由参数(PathParameter)和查询参数(QueryParameter)是非常常见的需求,下面我们就来看看Go语言... 目录一、路由参数 vs 查询参数二、Gin 获取路由参数和查询参数三、示例代码四、运行与测试1. 测试编程路