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

2024-03-31 11:12

本文主要是介绍探索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  01return 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.枚举的应用

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

运行结果:


下课了下课了~

下次还要来上课哦~ 

这篇关于探索C语言中的联合体和枚举:让处理数据更加得心应手的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl