探索C语言中的联合体和枚举:让处理数据更加得心应手

✨✨小新课堂开课了,欢迎欢迎~✨✨

🎈🎈养成好习惯,先赞后看哦~🎈🎈

所属专栏:http://t.csdnimg.cn/Oytke

小新的主页:编程版小新-CSDN博客

C语言中有内置类型, 比如:int ,char,short ,double,float等,但是仅用这些是不方便使用的,此次有了自定义类型,给了程序员更大的权力,以更好的追求性能。联合体能够将不同的类型聚在一起,放在一个共同的空间里,仿佛一损俱损,一荣俱荣。而枚举类型的使用仿佛更加的贴近生活,比如表述一个星期有七天,一年有12个月等。用枚举来写,增加代码的可读性和可维护性。

一:联合体类型 

1.联合体的定义

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

联合体的特点是所有成员共用同一块内存空间。所以联合体也叫:共用体

给联合体其中⼀个成员赋值,其他成员的值也跟着变化。

2.联合体的声明

union un   //   联合体关键字union+tag 标签
{
    int i;
    char c;     //  variable-name 联合体成员
    float f;
} a,b,c;   //  variable-list 变量列表

(1) 普通联合体

union un
{
    int i;
    char c;
    float f;
};

(2)嵌套联合体

//嵌套联合体
union u1
{
	int arr[4];
	float f;
};

union un
{
	int i;
	char c;
	union u1 u;
};

 (3)匿名联合体

//匿名联合体
union
{
	char s;
	int b;
	float f;
};

小新:匿名联合体是一种比较特殊的联合体,匿名联合体顾名思义就是省略了它的名字,也就是所谓的tag-标签。匿名联合体只能使用一次,下次再要使用的时候,它已经不在了,这点要注意。

(4)typedef重命名的联合体

//typedef重命名的联合体
typedef union un
{
	int i;
	char str[4];
};

 3.联合体变量的创建和初始化

//联合体变量的创建和初始化
union un
{
	int i;
	char c;
};

int main()
{
	//union un u = { 4,'s' };  //与结构体不同,这样初始化是错误的
	union un u = { 0 };//因为结构体成员公用一块内存区域,使用在初始化的时候只能初始化一个值
	return 0;
}

4.联合体的访问

联合体可以通过成员访问运算符(.)来访问其成员。与结构体相同,可以使用联合体变量和指向联合体的指针来访问成员。

#include<stdio.h>
#include<string.h>
union un
{
	int i;
	char c[10];
};

int main()
{
	union un u = { 0 };
	printf("%d ", u.i);
	strcpy(u.c, "xiaoxin");
	printf("%s ",u.c );
	return 0;
}

运行结果:

5.联合体的特点 

联合的成员是共用同⼀块内存空间的,这样⼀个联合变量的大小,至少是最大成员的大小(因为联合 至少得有能力保存最大的那个成员)。

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

运行结果:

用画图的方式来解释就是这样的。

 

6.联合体大小的计算 

联合体在计算大小的时候和结构体一样,遵循着某种规则。

什么规则呢,如下:

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

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

 示例1:

#include<stdio.h>
union Un1
{
              
	char c[5];
    int i;
};
union Un2
{
	short c[7];
	int i;
};
int main()
{
	//下⾯输出的结果是什么? 
	printf("%d\n", sizeof(union Un1));//
	printf("%d\n", sizeof(union Un2));
	return 0;
}

运行结果:

VS默认的最大对齐数是8,Un1的最大成员的大小是5,不是最大对齐数的整数倍,最终改为8;

Un2的最大成员的大小是14,不是最大对齐数的整数倍,最终改为16。 

7.联合体的应用

使用联合体是可以节省空间的,举例:

比如,我们要搞⼀个活动,要上线⼀个礼品兑换单,礼品兑换单中有三种商品:图书、杯⼦、衬衫。 每⼀种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。

图书:书名、作者、页数

杯子:设计

衬衫:设计、可选颜⾊、可选尺⼨

那我们不耐心思考,直接写出⼀下结构:

struct gift_list
{
 //公共属性 
 int stock_number;//库存量 
 double price; //定价 
 int item_type;//商品类型 
 
 //特殊属性 
 char title[20];//书名 
 char author[20];//作者 
 int num_pages;//⻚数 
 
 char design[30];//设计 
 int colors;//颜⾊ 
 int sizes;//尺⼨ 
};

上述的结构其实设计的很简单,用起来也方便,但是结构的设计中包含了所有礼品的各种属性,这样 使得结构体的大小就会偏大,比较浪费内存。因为对于礼品兑换单中的商品来说,只有部分属性信息是常用的。

比如: 商品是图书,就不需要design、colors、sizes。 所以我们就可以把公共属性单独写出来,剩余属于各种商品本身的属性使用联合体,这样就可以减少所需的内存空间,⼀定程度上节省了内存。

struct gift_list
{
 int stock_number;//库存量 
 double price; //定价 
 int item_type;//商品类型 
 
 union
{
 struct //匿名结构体
 {
 char title[20];//书名 
 char author[20];//作者 
 int num_pages;//⻚数 
 }book;

 struct //匿名结构体
 {
 char design[30];//设计 
 }mug;

 struct //匿名结构体
 {
 char design[30];//设计 
 int colors;//颜⾊ 
 int sizes;//尺⼨ 
 }shirt;

}item;

};

8.用联合体判断大小端

int check_sys()
{
 union
 {
 int i;
 char c;
 }un;
 un.i = 1;//00  00  00  01
 return un.c;//返回1是⼩端,返回0是⼤端 
}

二:枚举类型 

1.枚举类型的定义

枚举是一种特殊的数据类型,用于定义一组有限的命名常量,这些命名常量又被称为枚举常量,它提供了一种简洁,可读性更高的方式来表示这些常量,并且通常具有类型安全性和可扩展性。

在实际应用中我们经常把能够且便于一一列举的类型用枚举来表示。

2.枚举的声明

enum  枚举类型名

{

   标识符1,

   标识符2,

   ...

};

 (1) 普通枚举

enum un
{
	  MON=1, //指定从1开始,否则默认从0开始
      TUE,
      WED,
      THU, 
      FRI, 
      SAT, 
      SUN
};

(2)匿名枚举

 //匿名枚举
enum
{
	MON = 1, //指定从1开始,否则默认从0开始
    TUE,
	WED,
	THU,
    FRI,  
	SAT,
	SUN
};

(3)typedef重命名的枚举

 typedef enum day
{
	MON = 1, //指定从1开始,否则默认从0开始
	TUE,
	WED,
	THU,
	FRI,
	SAT,
	SUN
};

3.枚举的特点

小新:我们用一些例子来说明它的特点吧

#iclude<stdio.h>
enum un
{
	MON, 
	TUE,
	WED,
	THU,
	FRI,
	SAT,
	SUN
};

int main()
{
	
	for (int i = MON; i <= SUN; i++)
	{
		printf("%d ", i);
	}

	return 0;
}

运行结果:

{ }中的内容是枚举类型的可能取值,也叫枚举常量 。这些可能取值都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值

有请下一个例子登场

#include<stdio.h>
enum un
{
	red = 2,
	green,
	yellow,
	pink = 7,
	black,
	blue
};

int main()
{
	printf("red = %d ",red);
	printf("green = %d ", green);
	printf("yellow = %d ", yellow);
	printf("pink = %d ", pink);
	printf("black= %d ", black);
	printf("blue = %d ", blue);
	return 0;
}

运行结果:

也可以通过这种赋值的方式改变取值

4.枚举常量的创建和初始化 

我们通常是用枚举常量来给枚举变量赋值的,在C语言中也可以用整数给枚举变量赋值,但是在C++中不能,C++要求的更加严格一些。

#include<stdio.h>
typedef enum un
{
	MON, 
	TUE,
	WED,
	THU,
	FRI,
	SAT,
	SUM
}un;

int main()
{
	 un u = MON;//最好用枚举常量进行赋值
	return 0;
}

5.枚举类型的大小

枚举类型的大小和int的大小相等,都是4个字节,不信的话,小新就来证明一下。

#include<stdio.h>
enum day
{
	MON, 
	TUE,
	WED,
	THU,
	FRI,
	SAT,
	SUN
};

enum color
{
	red,
	blue,
	yellow,
	green
};

int main()
{
	printf("%zd\n", sizeof(enum day));
	printf("%zd\n", sizeof(enum color));
	return 0;
}

运行结果:

6.枚举类型的优点 

为什么使用枚举? 我们可以使用 #define 定义常量,为什么非要使用枚举?

枚举的优点:

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

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

3. 便于调试,预处理阶段会删除 #define 定义的符号

4. 使用方便,⼀次可以定义多个常量

5. 枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用

7.枚举的应用

计算器的实现有多种方法,今天我们用枚举来实现计算器

运行结果:


下课了下课了~

下次还要来上课哦~ 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue3封装Element表格

配置表头配置多选配置序号自定义操作列按钮 封装表格 Table.vue <template><el-table:data"tableData"width"100%":maxHeight"maxHeight"v-bind"$attrs"selection-change"handleSelectChange"row-click"hand…

【Python】Scrapy 爬虫(简单了解)

Scrapy项目开发流程 1.创建项目 打开cmd scrapy startproject example 就可以创建一个Scrapy项目。这时&#xff0c;我们找到并打开这个文件。 复制路径&#xff1a;C:\Users\25194\example 复制到pycharm里面&#xff0c;打开该项目。 文件介绍 scrapy.cfg setting表明项…

竞赛课第四周(八数码问题+八皇后问题)

目的&#xff1a; 1. 掌握递归和排序 2. 掌握BFS与队列 3. 掌握DFS和递归 4. 熟悉并理解回溯问题 实验内容&#xff1a; 1.八数码问题&#xff1a; 在一个33的棋盘上&#xff0c;放置编号为1~8的8个方块&#xff0c;每个占一格&#xff0c;另外还有一个空格。与空格相邻…

基于ssm的平面设计课程在线学习平台系统(java项目+文档+源码)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的平面设计课程在线学习平台系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 前台功能&#xf…

(南京观海微电子)——DDIC显示触控芯片介绍

显示驱动芯片&#xff08;Display Driver Integrated Circuit&#xff0c;简称DDIC&#xff09;的主要功能是控制OLED显示面板。它需要配合OLED显示屏实现轻薄、弹性和可折叠&#xff0c;并提供广色域和高保真的显示信号。同时&#xff0c;OLED要求实现比LCD更低的功耗&#xf…

【保姆级教程】YOLOv3图像目标检测:训练自己的数据集

一、YOLOv3图像目标检测原理 二、YOLOv3代码及预训练权重下载 2.1 下载yolov3代码 这里使用的是B站大佬Bubbliiiing复现的yolov3代码 仓库地址&#xff1a; https://github.com/bubbliiiing/yolo3-pytorch 2.2 下载模型预训练权重unet_resnet_medical.pth 链接&#xff1a…

网络基础(二)——HTTP协议

目录 1、2个简单的预备知识 2、HTTP请求和响应的格式 3、实现一个最简单的httpserver 4、HTTP的细节字段 4.1、GET和POST 4.2、HTTP的状态码 4.3、HTTP常见Header 1、2个简单的预备知识 首先我们来看一个域名&#xff1a;http://www.baidu.com/&#xff0c;很明显这是百…

实验三智能手机互联网程序设计(微信程序方向)实验报告

实验目的和要求 请编写下方商品列表页面&#xff0c;展示商品名称和价格&#xff1b; 二、实验步骤与结果&#xff08;给出对应的代码或运行结果截图&#xff09; Index.WXML <view class"shop" wx:for"{{10}}"> <vie…

40.网络游戏逆向分析与漏洞攻防-角色管理功能通信分析-角色删除功能的数据包失败的分析

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果 内容参考于&#xff1a; 易道云信息技术研究院VIP课 上一个内容&#xff1a;39.角色数据的维…

如何通过cookie来区分这是瑞数反爬的几代

一、以下仅个人观点&#xff0c;可能有误 1、瑞数反爬了解 瑞数反爬&#xff1a;大多数首次不带cookie的请求&#xff0c;响应状态码是202/412瑞数的cookie &#xff1a; 我们看PPT结尾的Cookie的来定位是几代&#xff0c;PT的是js生成的&#xff1b; 不看OS的&#xff0c;OS…

SQLite版本3中的文件锁定和并发(七)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;自己编译SQLite或将SQLite移植到新的操作系统&#xff08;六&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 正文&#xff1a; 1.0 SQLite 版本 3 中的文件锁定和并发 SQLite 版本 3.0.0 引入了新的锁…

【蓝桥杯嵌入式】六、真题演练(一)-1演练篇:第 届真题

温馨提示&#xff1a; 真题演练分为模拟篇和研究篇。本专栏的主要作用是记录我的备赛过程&#xff0c;我打算先自己做一遍&#xff0c;把遇到的问题和不同之处记录到演练篇&#xff0c;然后再返回来仔细研究一下&#xff0c;找到最佳的解题方法记录到研究篇。 解题记录&#x…

Yarn的安装及使用(1):安装

一、Yarn的安装 在不同操作系统上安装Yarn的步骤和注意事项&#xff1a; 1、Windows 1.1 通过.msi安装程序安装&#xff1a; 步骤&#xff1a; 访问 Yarn官方网站 下载适用于Windows的.msi安装包。 运行下载好的.msi文件&#xff0c;按照向导进行安装。 在安装过程中&#…

Apache Hive的基本使用语法(一)

一、数据库操作 创建数据库 create database if not exists myhive;查看数据库 use myhive; desc database myhive;创建数据库并指定hdfs存储 create database myhive2 location /myhive2;删除空数据库&#xff08;如果有表会报错&#xff09; drop database myhive;…

爱上数据结构:栈和队列的概念及使用

​ ​ &#x1f525;个人主页&#xff1a;guoguoqiang. &#x1f525;专栏&#xff1a;数据结构 ​ 一、栈 1.栈的基本概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶&#xff0c;…

酒店管理系统项目用例图及用例说明

1、系统功能模块图 2、部分系统功能模块说明 &#xff08;1&#xff09;查询房间剩余 模块名称&#xff1a;管理员登录 编号&#xff1a;1-1 主要功能&#xff1a;验证管理员登录用户名及密码 上级调用模块&#xff1a;无 下级调用模块&#xff1a; 约束&#xff1a; &a…

强化基础-Java-泛型基础

什么是泛型&#xff1f; 泛型其实就参数化类型&#xff0c;也就是说这个类型类似一个变量是可变的。 为什么会有泛型&#xff1f; 在没有泛型之前&#xff0c;java中是通过Object来实现泛型的功能。但是这样做有下面两个缺陷&#xff1a; 1 获取值的时候必须进行强转 2 没有…

音视频开发之旅(80)- AI数字人-腾讯开源AniPortrait-音频驱动的肖像动画

目录 1、前言 2、效果展示 3、原理学习 4、遇到的问题与解决方案 5、资料 一、前言 一个月前阿里Emo发布&#xff0c;通过音频驱动的非常自然的肖像视频&#xff0c;引起很大反响。具体看下面的视频&#xff0c;但是并没有开源其代码。 这两天腾讯开源了其音频驱动的肖像…

2024年美团笔试题(1)

一.题目描述 小美拿到了一个排列&#xff0c;其中初始所有元素都是红色&#xff0c;但有些元素被染成了白色。 小美每次操作可以选择交换任意两个红色元素的位置。她希望操作尽可能少的次数使得数组变成非降序&#xff0c;你能帮帮她吗? 排列是指:一个长度为n的数组&#…

Java | Leetcode Java题解之第1题两数之和

题目&#xff1a; 题解&#xff1a; class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer, Integer> map new HashMap<>();for(int i 0; i< nums.length; i) {if(map.containsKey(target - nums[i])) {return new int[] {map.get(tar…