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

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

目录

前言

一、联合体(共用体)

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.xdnf.cn/news/1401643.html

相关文章:

  • Linux IO复用
  • 优选算法:二分查找
  • 数据库攻略:“CMU 15-445”Project0:C++ Primer(2024 Fall)
  • 《Java反射与动态代理:从原理到实践》
  • SpringBoot整合Actuator实现健康检查
  • MIT 6.5840 (Spring, 2024) 通关指南——Lab 1: MapReduce
  • GitHub 热榜项目 - 日榜(2025-08-30)
  • 基于Ubuntu本地GitLab 搭建 Git 服务器
  • 解构机器学习:如何从零开始设计一个学习系统?
  • 【LeetCode】大厂面试算法真题回忆(121) —— 经典屏保
  • 并发编程——09 CountDownLatch源码分析
  • Spring Boot 后端接收多个文件的方法
  • 项目管理常用的方法有哪些
  • 三菱 PLC的中断指令/中断指针
  • 构建现代化的“历史上的今天“网站:从API到精美UI的全栈实践
  • 北方苍鹰优化算法优化的最小二乘支持向量机NGO-LSSVM多输入多输出回归预测【MATLAB】
  • 2025年06月 Scratch 图形化(二级)真题解析#中国电子学会#全国青少年软件编程等级考试
  • Robolectric如何启动一个Activity
  • 倾斜摄影是选择RGB图像还是多光谱影响进行操作?
  • Transformer:从入门到精通
  • 嵌入式Linux驱动开发:蜂鸣器驱动
  • stack queue的实现 deque的底层结构 priority_queue的实现
  • 【Java实战⑦】从入门到精通:Java异常处理实战指南
  • 漫谈《数字图像处理》之分水岭分割
  • AUTOSAR进阶图解==>AUTOSAR_TR_ClassicPlatformReleaseOverview
  • 计算机毕设项目 基于Python与机器学习的B站视频热度分析与预测系统 基于随机森林算法的B站视频内容热度预测系统
  • observer pattern 最简上手笔记
  • 如何调整Linux系统下单个文件的最大大小?
  • hadoop安欣医院挂号看诊管理系统(代码+数据库+LW)
  • 2025年高性能计算年会