联合体和枚举——嵌入式学习笔记

目录

前言

一、联合体(共用体)

1、基本概念

2、初始化和引用

(1)初始化

(2)引用

二、枚举


前言

        在C语言的编程世界中,我们早已熟悉了结构体struct这种能将不同数据类型捆绑在一起的“打包”神器。但你是否想过,如果有一块内存,可以灵活地存放不同类型的数据,但在同一时刻只使用其中一种,该如何实现?又是否曾为那些 magic number(魔法数字)和意义不明的整数常量而头疼?

        这就是联合体(union)和枚举(enum)大显身手的地方。它们一个是高效利用内存的“变体”专家,一个是提升代码可读性与安全性的“语义化”大师。本篇博客将带你深入浅出,探索这两个强大工具的奥秘,让你的C代码更加专业、优雅和高效。


一、联合体(共用体)

1、基本概念

说明:

        联合体的外在形式跟结构体非常相似,但它们有一个本质的区别:结构体中的各个成员各自独立,而联合体的各个成员却共用一块内存,因此联合体也称为共用体

图解:

        

特点:

        整个联合体变量的尺寸,取决于联合体尺寸最大的成员

        给联合体的某个成员赋值,会覆盖其他成员,使它们失效

        

        联合体各成员之间形成一个 "互斥"的逻辑的,在某一个时刻只有一个成员有效

语法:

        联合体标签:用来区分各个不同的联合体

        成员: 是包含在联合体内部的数据,可以是任意的数据类型

基本结构:

union 联合体标签
{成员1;成员2;...        
};

2、初始化和引用

(1)初始化

说明:

        联合体的操作跟结构体形式上别无二致,但由于联合体特殊的存储特性,不管怎么初始化和赋值,最终有且仅有一个成员是有效的

示例代码:

        

#include <stdio.h>union node1
{char ch;        // A、B、C、Dint num;        // 60、70、80、90、100double f;       // 99.9、59.9char buf[128];  // 优秀、良好、中等、及格、差
};union node2
{char ch;        // A、B、C、Dint num;        // 60、70、80、90、100
};// 主函数
int main(int argc, char const *argv[])
{// (1)、联合体的初始化// 1、普通初始化union node1 n1 = {'A', 90, 99.9, "优秀"};printf("联合体成员的值 == %d\n",  n1.ch);printf("n1的大小为    == %lu\n", sizeof(n1));   // - 整个联合体变量的尺寸,取决于联合体尺寸最大的成员/*报警告:warning: excess elements in union initializer// 翻译:警告:联合体初始化器中的元素过多原因:只有第一个成员有效,其它成员赋值无效,也无需赋值- 给联合体的某个成员赋值,会覆盖其他成员,使它们失效- 联合体各成员之间形成一个 "互斥"的逻辑的,在某一个时刻只有一个成员有效*/// 2、指定成员初始化(只有最后一个赋值有效,其它赋值无效,会被覆盖)union node2 n2 ={.num = 80,.ch  = 'D'};printf("联合体的成员的值 == %c\n", n2.ch);printf("联合体的成员的值 == %d\n", n2.num);printf("n2的大小为      == %lu\n", sizeof(n2));return 0;
}

(2)引用

说明:

        联合体一般很少单独使用,而经常以结构体的成员形式存在,用来表达某种互斥的属性

示例代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>union node1
{char ch;        // A、B、C、Dint num;        // 60、70、80、90、100double f;       // 99.9、59.9char buf[128];  // 优秀、良好、中等、及格、差
};union node2
{char ch;        // A、B、C、Dint num;        // 60、70、80、90、100
};typedef struct student       
{char name[128];     char phone[128];int id;int gender;char class[128];float height;float weight;int age;union node1 score;   // 里面有四种互斥的属性}stu_t, *stu_p;         // 主函数
int main(int argc, char const *argv[])
{// (1)、联合体的初始化// 1、普通初始化union node1 n1 = {'A', 90, 99.9, "优秀"};printf("联合体成员的值 == %d\n",  n1.ch);printf("n1的大小为    == %lu\n", sizeof(n1));   // - 整个联合体变量的尺寸,取决于联合体尺寸最大的成员/*报警告:warning: excess elements in union initializer// 翻译:警告:联合体初始化器中的元素过多原因:只有第一个成员有效,其它成员赋值无效,也无需赋值- 给联合体的某个成员赋值,会覆盖其他成员,使它们失效- 联合体各成员之间形成一个 "互斥"的逻辑的,在某一个时刻只有一个成员有效*/// 2、指定成员初始化(只有最后一个赋值有效,其它赋值无效,会被覆盖)union node2 n2 ={.num = 80,.ch  = 'D'};printf("联合体的成员的值 == %c\n", n2.ch);printf("联合体的成员的值 == %d\n", n2.num);printf("n2的大小为      == %lu\n", sizeof(n2));// (2)、联合体的引用// 1、联合体的直接引用(最后的赋值,会将整个联合体全部覆盖)n1.ch   = 'C';n1.num  = 120;n1.f    = 59.9;strcpy(n1.buf , "优秀+");printf("n1.buf == %s\n", n1.buf);// 2、联合体的间接引用(最后的赋值,会将整个联合体全部覆盖)union node1 *p1 = &n1;                          // 指针指向的内存的是栈区union node1 *p2 = malloc(sizeof(union node1));  // 指针指向的内存的是堆区(无初始化)bzero(p2, sizeof(union node1));// 栈区指针strcpy(p1->buf, "良好");p1->ch  = 'E';p1->num = 220;p1->f   = 6.28;printf("p1->f == %f\n", p1->f);// 堆区指针strcpy(p2->buf, "中等");p2->num = 330;p2->f   = 12.56;p2->ch  = 'F';printf("p2->f == %c\n", p2->ch);// (3)、联合体的实际的引用例子struct student stu1 = {0};stu1.score.num = 100;       /*此处可以选择一下四种评价标准,但同一时间内只能够选择其中一种ch;      // A、B、C、Dnum;     // 60、70、80、90、100f;       // 99.9、59.9;        // 优秀、良好、中等、及格、差*/return 0;
}


二、枚举

说明:

        枚举类型的本质是提供一种范围受限的类型,比如用0-6表示7种颜色,用0-3表示4种状态,但枚举在C语言种并未实现其本来应用的效果,直到C++才拥有原本该有的属性

        是使用有意义的单词,来代替无意义的数字,提高程序的可读性...

语法:

        enum是关键字

        spectrum是枚举常量列表标签,省略的情况下无法定义枚举变量

格式:

enum 枚举常量列表标签
{常量1,常量2,...
}

例子:

// 枚举类型
enum color{red, orange, yellow=8, green, blue, cyan, purple};
enum {reset, running, sleep, stop};// 枚举变量
enum color c = yellow;    // 等价于c = 2

要点:

        枚举常量实质上就是整型,首个 枚举常量默认为0

        枚举常量在定义时可以赋值,若不赋值,则取值前面的枚举常量的值加1

        C语言种,枚举等价于整型,支持整型数据的一切操作

示例代码:

#include <stdio.h>// stm32的枚举的使用(相比define的好处是可以归类,并且可以迅速且大规模的铺开)
typedef enum IRQn
{/******  Cortex-M4 Processor Exceptions Numbers ****************************************************************/NonMaskableInt_IRQn         = -14,    /*!< 2 Non Maskable Interrupt                                          */MemoryManagement_IRQn       = -12,    /*!< 4 Cortex-M4 Memory Management Interrupt                           */BusFault_IRQn               = -11,    /*!< 5 Cortex-M4 Bus Fault Interrupt                                   */UsageFault_IRQn             = -10,    /*!< 6 Cortex-M4 Usage Fault Interrupt                                 */SVCall_IRQn                 = -5,     /*!< 11 Cortex-M4 SV Call Interrupt                                    */DebugMonitor_IRQn           = -4,     /*!< 12 Cortex-M4 Debug Monitor Interrupt                              */PendSV_IRQn                 = -2,     /*!< 14 Cortex-M4 Pend SV Interrupt                                    */SysTick_IRQn                = -1,     /*!< 15 Cortex-M4 System Tick Interrupt                                *//******  STM32 specific Interrupt Numbers **********************************************************************/// ...
}IRQn_Type;// 表示颜色
enum color      // 有标签,所以能定义变量
{red,        // 没有赋值默认为0(后面的值依次+1)orange,     // 1yellow,     // 2green=8,    // 如果赋值了,那么从此数据开始,后面依次+1(前面数据依然遵循前面的规则)blue,       // 9cyan,       // 10   purple      // 11
};
enum            // 没有标签,所以不能定义变量
{reset,      // 重启running,    // 运行sleep,      // 休眠stop        // 停止,关机
};// 主函数
int main(int argc, char const *argv[])
{// (1)、枚举类型默认初始化和引用enum color c = 1;c = c + 1;printf("c == %d\n", c); // 枚举等价于整型,支持整型数据的一切操作1// (2)、在实际开发种使用(是使用有意义的单词,来代替无意义的数字,提高程序的可读性...)// 枚举等价于整型,支持整型数据的一切操作2// 1、颜色选择enum color c_num = 0;printf("请选择颜色:\n");printf("0、红色\n");printf("1、橙色\n");printf("2、黄色\n");scanf("%d", (int*)&c_num);  while(getchar()!='\n');switch (c_num){case red:printf("我是红红!\n");break;case orange:printf("我是橙橙!\n");break;case yellow:printf("我是黄黄!\n");break;}// 2、机器状态选择同上return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SRE命令行兵器谱之思想篇:像SRE一样思考——命令行不只是工具,更是你的战友

SRE命令行兵器谱之思想篇:像SRE一样思考——命令行不只是工具,更是你的战友 欢迎来到《SRE命令行兵器谱》系列。在深入研究 grep, lsof, tcpdump 这些强大“兵器”的细节之前,我们必须先回答一个更重要的问题: 一个SRE(网站可靠性工程师)在黑色的终端窗口前,脑子里想的…

STL库——list(类模拟实现)

ʕ • ᴥ • ʔ づ♡ど &#x1f389; 欢迎点赞支持&#x1f389; 个人主页&#xff1a;励志不掉头发的内向程序员&#xff1b; 专栏主页&#xff1a;C语言&#xff1b; 文章目录 前言 一、基本框架 二、构造函数 三、析构函数 四、赋值重载 五、增删查改 5.1、push_front/pus…

在PowerPoint和WPS演示让蝴蝶一直跳8字舞

如何让PPT中插入的对象按指定的轨迹运动并且一直“停不下来”&#xff1f;简单三步&#xff1a;①插入对象、②设置路径动画、③设置动画重复。本文以蝴蝶图片一直跳8字舞为例进行实际操作讲解&#xff0c;PowerPoint和WPS演示都一样操作&#xff0c;本文以WPS演示进行讲解。第…

并发编程——06 JUC并发同步工具类的应用实战

0 常用并发同步工具类的真实应用场景JDK 提供了比synchronized更加高级的各种同步工具&#xff0c;包括ReentrantLock、Semaphore、CountDownLatch、CyclicBarrier等&#xff0c;可以实现更加丰富的多线程操作&#xff1b;1 ReentrantLock&#xff08;可重入的占用锁&#xff0…

Apple登录接入记录

Apple文档——通过 Apple 登录 使用入门 - 通过 Apple 登录 - Apple Developer Apple文档——设计要求——登录通过 Apple 登录 | Apple Developer Documentation 插件github版——apple-signin-unity&#xff08;README 中为接入步骤&#xff09; GitHub - lupidan/apple-…

【小程序-慕尚花坊04】网络请求并发与loading

网络请求并发与loading一&#xff0c;网络请求并发与loading1&#xff0c;并发处理1.1&#xff0c;异步实现方式2.2&#xff0c;Promise.all异步方式封装2&#xff0c;loading加载2.1&#xff0c;loading的基本使用2.2&#xff0c;loading与并发结合案例2.3&#xff0c;loading…

CentOS 7 升级 OpenSSH 10.0p2 完整教程(含 Telnet 备份)

&#x1f539; CentOS 7 升级 OpenSSH 10.0p2 完整教程&#xff08;含 Telnet 备份&#xff09; 注意&#xff1a;为了避免升级 SSH 时无法远程登录&#xff0c;建议先启用 Telnet 服务 作为备用连接方式。 CentOS 7 默认 OpenSSH 版本是 7.x&#xff0c;升级到 10.0p2 需要 源…

aragfw9.dll aqnky-ef.dll aqua dock.dll apscon~1.dll apropdll.dll app_web_yqnqasrp.dll app_web_

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

rabbitMQ延时队列实现,怎么保证消息的幂等

一、RabbitMQ 延时队列实现方式 基于 TTL&#xff08;Time-To-Live&#xff09; 死信队列&#xff08;Dead Letter Queue&#xff09; 这是最常用的实现方式&#xff0c;核心思路是&#xff1a; (1)消息设置过期时间&#xff08;TTL&#xff09; (2)消息过期后进入绑定的死信队…

前沿技术观察:从AI 时代到量子计算的下一站

前沿技术观察&#xff1a;从AI 时代到量子计算的下一站&#x1f680; 技术的浪潮一波接一波&#xff0c;从 人工智能 到 区块链&#xff0c;再到 边缘计算、元宇宙、量子计算&#xff0c;这些前沿技术正在深刻影响我们的生活与产业格局。 对于开发者和技术爱好者来说&#xff0…

通过Kubernetes安装mysql5服务

以下是清晰、结构化的操作流程优化说明&#xff0c;按步骤梳理从部署到配置持久化、暴露服务的完整过程&#xff1a;一、基础部署&#xff1a;快速验证 MySQL 可用性创建有状态工作负载进入 KubeSphere 项目 → 工作负载 → 有状态副本集 → 创建&#xff0c;选择 通过镜像创建…

【mysql】SQL 中 IS 与 = 的区别:一个 NULL 值引发的思考

SQL 中 IS 与 的区别&#xff1a;一个 NULL 值引发的思考为什么查询结果总是少一条数据&#xff1f;可能是 NULL 在捣鬼在 SQL 查询中&#xff0c;很多开发者都曾遇到过这样的困惑&#xff1a;明明看起来正确的查询语句&#xff0c;返回的结果却总是与预期不符。这往往是因为没…

openGauss笔记

1、安装 直接用docker安装 2、国产化 符合国产化要求 3、客户端 3.1 dbeaver 社区版本&#xff08;25.1.4&#xff09;即可&#xff0c;驱动建议用离线版本&#xff0c;在官网下载最新的&#xff0c;然后在驱动管理里面进行添加本地的jar 3.1.1 驱动配置3.1.2 依赖 需要java版本…

SQL语言增删改查之C与R

本节通关要求1、掌握 SQL 语句对数据库进行的创建 Create 和读取 Retireve 操作的指令&#xff1b;2、多练习&#x1f3ae;说明&#xff1a;操作对象是数据表中的数据行&#xff0c;也就是表中的记录。请明确操作对象&#xff0c;不要误伤友军。背景&#xff1a;create table i…

栈溢出问题

brpc 的 bthread 默认协程栈大小是 128KB&#xff08;非 pthread 模式&#xff09;。如果在一个bthread中&#xff0c;它执行的函数内定义了一个局部变量map&#xff0c;有很多个元素&#xff0c;map的大小超过了128KB&#xff0c;协程会自动申请新的栈空间吗&#xff1f;这里要…

Android之穿山甲广告接入

文章目录前言一、效果图二、实现步骤1.引入库2.build.gradle依赖3.Application初始化3.开屏广告4.插屏广告5.懒人做法总结前言 项目接入广告已经是常见的现象了&#xff0c;但是还有很多朋友或者初学者没有接触过&#xff0c;或者没有接触过穿山甲&#xff0c;今天就来看一下&…

Web开发工具一套式部署Maven/Nvm/Mysql/Redis

前言&#xff1a; 对于一个纯小白且电脑没有任何环境的计算机学生&#xff0c;如何快速跑通Java前后端项目呢&#xff1f; 先附上百度网盘 地址&#xff1a; Web开发工具 。 以下链接来自不同作者&#xff0c;如有侵犯&#xff0c;请联系我删除。 1.Jdk 部署地址&#xff1a…

Deepseek法务提示指令收集

参考网络资料&#xff0c;收集一些法务提示指令&#xff0c;可用于Agent LLM、以及LLM法律相关开发。 https://zhuanlan.zhihu.com/p/22588251815 1 基础指令 1) 身份认证模块 【身份与版本声明】 您是由DeepSeek研发的法律智能辅助系统V4.2版&#xff0c;内核经司法部《生成…

Tiptrans转运 | 免费5国转运地址

Tiptrans 是一家总部位于捷克的国际包裹转运与虚拟地址服务平台&#xff0c;主要提供全球虚拟收货地址&#xff08;英国、德国、香港、美国等&#xff09;&#xff0c;让用户在当地网店购物&#xff0c;再由 Tiptrans 转运到海外。除了物流服务&#xff0c;Tiptrans 也提供虚拟…

STM32手动移植FreeRTOS

&#x1f4e6; 准备工作 获取FreeRTOS源码: 访问 FreeRTOS官网 或其 GitHub仓库 下载最新版内核源码。 你也可以使用Git克隆&#xff08;注意要包含子模块&#xff09;&#xff1a;git clone https://github.com/FreeRTOS/FreeRTOS.git --recurse-submodules。 准备STM32基础…