单片机软件架构连载(3)-typedef

今天给大家讲typedef,这个关键字在实际产品开发中,也是海量应用。

技术涉及知识点比较多,有些并不常用,我们以贴近实际为原则,让大家把学习时间都花在重点上。

1.typedef的概念

typedef 是 C 语言中的一个关键字,可以为基本数据类型、结构体、联合体、枚举等创建一个新的类型名,有助工程师编写更清晰、更易于维护的代码。

2.typedef的几种用法

2.1用于基本数据类型

// 使用typedef关键字定义一个新类型名uint8_t,它代表无符号的8位字符(即0到255的整数)
typedef unsigned char uint8_t;

// 使用typedef关键字定义一个新类型名uint16_t,它代表无符号的16位短整型(即0到65535的整数)
typedef unsigned short uint16_t;

// 使用typedef关键字定义一个新类型名uint32_t,它代表无符号的32位整型(即0到4294967295的整数)
typedef unsigned int uint32_t;

// 声明一个类型为uint8_t的变量a,可以存储8位无符号整数
uint8_t a;

// 声明一个类型为uint16_t的变量b,可以存储16位无符号整数
uint16_t b;

// 声明一个类型为uint32_t的变量c,可以存储32位无符号整数
uint32_t c;

这段代码用typedef给unsigned char、unsigned short 和 unsigned int分别创建了uint8_t、uint16_t、uint32_t别名。

这里使用typedef给数据类型创建别名有什么作用或优势?

①.提高代码可读性

通过使用 uint8_t、uint16_t 和 uint32_t 这样的类型名,比直接使用基本数据类型 unsigned char、unsigned short 和 unsigned int 更易于理解。

②跨平台兼容性

不同的编译器或平台可能对基本数据类型的大小有不同的定义(例如,某些编译器可能将 int 定义为 16 位或 64 位),如果将来换了编译器或平台,只需更改 typedef 的定义,而不必在代码库中搜索和替换每个变量定义,代码维护更加容易。

③定义变量时更加方便

不用每次都写 unsigned char、unsigned short 和 unsigned int。

2.2用于结构体

我们可以通过以下方式创建结构体。

struct USART_InitTypeDef
{
  uint32_t USART_BaudRate;        
  uint16_t USART_WordLength;        
  uint16_t USART_StopBits;     
  uint16_t USART_Parity;         
  uint16_t USART_Mode;           
  uint16_t USART_HardwareFlowControl;  
};

//定义结构体变量
struct USART_InitTypeDef stu_usart;

不过这种方式,每次定义结构体变量都要加struct .....,比较麻烦。

所以,我们可以用typedef关键字给结构体创建一个别名。

typedef struct
{
  uint32_t USART_BaudRate;        
  uint16_t USART_WordLength;        
  uint16_t USART_StopBits;     
  uint16_t USART_Parity;         
  uint16_t USART_Mode;           
  uint16_t USART_HardwareFlowControl;  
} USART_InitTypeDef;

//定义结构体变量
USART_InitTypeDef stu_usart;

使用typedef给结构体创建了别名USART_InitTypeDef,下次就可以直接使用USART_InitTypeDef去定义结构体变量,不用再写struct了,这样代码更加方便简洁。

这种方式,在STM32之类的库文件里,有海量的使用。

2.3用于枚举

typedef enum
{ 
    GPIO_Mode_AIN = 0x0,
    GPIO_Mode_IN_FLOATING = 0x04,
    GPIO_Mode_IPD = 0x28,
    GPIO_Mode_IPU = 0x48,
    GPIO_Mode_Out_OD = 0x14,
    GPIO_Mode_Out_PP = 0x10,
    GPIO_Mode_AF_OD = 0x1C,
    GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;

//定义枚举变量
GPIOMode_TypeDef GPIO_Mode;

这段代码定义了一个枚举类型,使用 typedef 关键字,这个枚举类型被赋予了一个别名GPIOMode_TypeDef,下次需要定义该枚举类型变量时,可直接使用GPIOMode_TypeDef xx,这样代码可读性更高,也简洁。

这种方式,在实际产品中,也是用的非常多嘀。

2.4用于函数指针

我们先来看看不用typedef的函数指针创建方法:

//代码示例1,不用typedef的函数指针

// 定义一个函数,形参为无符号字符类型,无返回值。
void KeyEventHandle1(unsigned char keys)
{
    //功能实现
}

void KeyEventHandle2(unsigned char keys)
{
    //功能实现
}

//定义了一个函数指针 KeyEvent_CallBack_t,并将KeyEventHandle函数的地址赋给它。
void (*KeyEvent_CallBack_t1)(unsigned char) = KeyEventHandle1;
void (*KeyEvent_CallBack_t2)(unsigned char) = KeyEventHandle2;

这种方式,如果需要重复去定义同样的函数指针,是比较麻烦的,每次定义函数指针变量都要写void (*函数指针变量名)(形参1)......

下面来看看用typedef创建函数指针。

//使用了typedef定义函数指针类型KeyEvent_CallBack_t
typedef void (*KeyEvent_CallBack_t)(unsigned char keys);

void KeyEventHandle1(unsigned char keys)
{
    //功能实现
}

void KeyEventHandle2(unsigned char keys)
{
    //功能实现
}


KeyEvent_CallBack_t KeyScanCBS1 = KeyEventHandle1;
KeyEvent_CallBack_t KeyScanCBS2 = KeyEventHandle2;

很明显,我们可以用KeyEvent_CallBack_t 这个函数指针类型,直接定义函数指针变量,这样比不用typedef的方式要方便简洁很多,特别是对于那些形参多的函数。

这种方式,我自己做产品时用的很多,我们无际项目特训营的项目3和6都有挺多这种应用。

以上,是我做产品接触最多的几种用法,还有其它的,比如typedef+数组,typedef+联合体,我个人用的比较少。

用法基本万变不离其宗,掌握这几种,看到其它的也基本能融会贯通。

3.typedef的优势总结

我们来总结下,typedef最主要的几点优势:

  • 提高代码可读性:通过使用有意义的类型名,代码更易于理解。

  • 简化复杂类型:对于结构体、枚举、函数指针等复杂类型,使用 typedef 可以简化变量定义。

  • 易于修改:如果基本类型需要更改,只需更改 typedef 定义,而不必修改使用该类型的所有实例。

  • 增加代码移植性:不同编译器或平台可能对某些数据类型的大小有差别(例如,int在某些平台上可能是16位,在另一些平台上可能是32位或64位)。通过使用 typedef,可以在不同的平台上定义相同的名字来代表具有适当大小和对齐的数据类型。


最近很多粉丝问我单片机怎么学,我根据自己从业十年经验,累积耗时一个月,精心整理一份「单

片机最佳学习路径+单片机入门到高级教程+工具包」全部无偿分享给铁粉!!!

除此以外,再含泪分享我压箱底的22个热门开源项目,包含源码+原理图+PCB+说明文档,让你迅速进阶成高手

教程资料包和详细的学习路径可以看我下面这篇文章的开头

《单片机入门到高级开挂学习路径(附教程+工具)》

《单片机入门到高级开挂学习路径(附教程+工具)》

《单片机入门到高级开挂学习路径(附教程+工具)》

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

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

相关文章

java wait, notify, notifyAll三个方法

wait(), notify(), 和 notifyAll() 是 Java 中用于线程间通信和同步的方法,它们都是 Object 类中的方法,而非 Thread 类的方法。这些方法通常与 synchronized 关键字一起使用,用于实现线程之间的协作和互斥访问共享资源。 关于生产者-消…

Apache Seata配置管理原理解析

本文来自 Apache Seata官方文档,欢迎访问官网,查看更多深度文章。 本文来自 Apache Seata官方文档,欢迎访问官网,查看更多深度文章。 Apache Seata配置管理原理解析 说到Seata中的配置管理,大家可能会想到Seata中适配…

传统IO和NIO文件拷贝过程

参考:https://blog.csdn.net/weixin_57323780/article/details/130250582

几个小创新模型,KAN组合网络(LSTM、GRU、Transformer)回归预测,python预测全家桶再更新!...

截止到本期,一共发了9篇关于机器学习预测全家桶Python代码的文章。参考往期文章如下: 1.终于来了!python机器学习预测全家桶 2.机器学习预测全家桶-Python,一次性搞定多/单特征输入,多/单步预测!最强模板&a…

【网络安全】实验三(基于Windows部署CA)

一、配置环境 打开两台虚拟机,并参照下图,搭建网络拓扑环境,要求两台虚拟的IP地址要按照图中的标识进行设置,并根据搭建完成情况,勾选对应选项。注:此处的学号本人学号的最后两位数字,1学号100…

《python程序语言设计》2018版第5章第52题利用turtle绘制sin函数

这道题是送分题。因为循环方式已经写到很清楚,大家照抄就可以了。 但是如果说光照抄可是会有问题。比如我们来演示一下。 import turtleturtle.penup() turtle.goto(-175, 50 * math.sin((-175 / 100 * 2 * math.pi))) turtle.pendown() for x in range(-175, 176…

k8s学习之cobra命令库学习

1.前言 打开k8s代码的时候,我发现基本上那几个核心服务都是使用cobra库作为命令行处理的能力。因此,为了对代码之后的代码学习的有比较深入的理解,因此先基于这个库写个demo,加深对这个库的一些理解吧 2.cobra库的基本简介 Git…

算法设计与分析 实验5 并查集法求图论桥问题

目录 一、实验目的 二、问题描述 三、实验要求 四、实验内容 (一)基准算法 (二)高效算法 五、实验结论 一、实验目的 1. 掌握图的连通性。 2. 掌握并查集的基本原理和应用。 二、问题描述 在图论中,一条边被称…

IDEA发疯导致maven下载回来的jar不完整zip END header not found

IDEA发疯导致maven下载回来的jar不完整zip END header not found 具体报错 java: 读取D:\mavenRepository\com\alibaba\druid-spring-boot-starter\1.2.23\druid-spring-boot-starter-1.2.23.jar时出错; zip END header not foundjava: java.lang.RuntimeException: java.io.…

Python视觉轨迹几何惯性单元超维计算结构算法

🎯要点 🎯视觉轨迹几何惯性单元超维计算结构算法 | 🎯超维计算结构视觉场景理解 | 🎯超维计算结构算法解瑞文矩阵 | 🎯超维矢量计算递归神经算法 🍪语言内容分比 🍇Python蒙特卡罗惯性导航 蒙…

【感谢告知】本账号内容调整,聚焦于Google账号和产品的使用经验和问题案例分析

亲爱的各位朋友: 感谢您对本账号的关注和支持! 基于对朋友们需求的分析和个人兴趣的转变,该账号从今天将对内容做一些调整,有原来的内容改为Google(谷歌)账号和产品的使用经验,以及相关问题的…

LeetCode 744, 49, 207

目录 744. 寻找比目标字母大的最小字母题目链接标签思路代码 49. 字母异位词分组题目链接标签思路代码 207. 课程表题目链接标签思路代码 744. 寻找比目标字母大的最小字母 题目链接 744. 寻找比目标字母大的最小字母 标签 数组 二分查找 思路 本题比 基础二分查找 难的一…

《python程序语言设计》2018版第5章第53题利用turtle绘制sin和cos函数 sin蓝色,cos红色和52题类似

直接上题和代码 5.53 (Turtle:绘制sin和cos函数)编写程序绘制蓝色的sin函数和红色的cos函数。 代码和结果 turtle.speed(10) turtle.penup() # sin 用蓝色 turtle.color("blue") #这道题和上道题一样,先把turtle放到起始…

pandas读取CSV格式文件生成数据发生器iteration

背景 数据集标签为csv文件格式,有三个字段column_hander [‘id’, ‘boneage’, ‘male’],需要自己定义数据集。文件较大,做一个数据发生器迭代更新数据集。 实现模板 在Pandas中,可以使用pandas.read_csv函数读取CSV文件&…

官网首屏:激发你的小宇宙和第六感,为了漂亮,干就完了。

官网的首屏是指用户打开网站后首先看到的页面,通常是整个网站最重要的一部分。首屏的设计和内容对于吸引用户的注意力、传达品牌形象和价值、促使用户继续浏览和进行交互非常关键。以下是官网首屏的重要性的几个方面: 1. 第一印象: 首屏是用…

Redis官方可视化管理工具

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl RedisInsight是一个Redis可视化工具,提供设计、开发和优化 Redis 应用程序的功能。RedisInsight分为免费的社区版和一个付费的企业版,免费版具有基本…

文心一言 VS 讯飞星火 VS chatgpt (297)-- 算法导论22.1 1题

一、给定有向图的邻接链表,需要多长时间才能计算出每个结点的出度(发出的边的条数)?多长时间才能计算出每个结点的入度(进入的边的条数)?如果要写代码,请用go语言。 文心一言: 计算出度 对于有向图的邻接链表表示&a…

C++ 引用——常量引用

作用:常量引用主要用来修饰形参,防止误操作 在函数形参列表中,可以加const修饰形参,防止形参改变实参 示例: 运行结果:

【Linux】进程优先级 + 环境变量

前言 在了解进程状态之后,本章我们将来学习一下进程优先级,还有环境变量等。。 目录 1.进程优先级1.1 为什么要有优先级? 2.进程的其他概念2.1 竞争性与独立性2.2 并行与并发2.3 进程间优先级的体现:2.3.1 O(1) 调度算法&#xf…

202406 CCF-GESP Python 四级试题及详细答案注释

202406 CCF-GESP Python 四级试题及详细答案注释 1 单选题(每题 2 分,共 30 分)第 1 题 小杨父母带他到某培训机构给他报名参加CCF组织的GESP认证考试的第1级,那他可以选择的认证语言有几种?( ) A. 1 B. 2 C. 3 D. 4答案:C解析:目前CCF组织的GESP认证考试有C++、Pyth…