好久没开文章了,有点手生,小伙伴们周末好,今天给大家分享一下宏定义,原本以为是很简单的小知识点,最近在别人的构架里发现看不懂了,发现了新大陆,必须拿来分享一下,首先来一下我们经常用到的宏定义,经常把常数定义成一个宏,如下:
#define MY_FIRST_MACRO 1 //(非常简单吧)
接下来看看最近我在分析QF框架时的境遇吧,对于QF来讲,因为他要做时间管理,所以需要一个QF_tick()处理,随便打开了一个bsp.c如下:
第一眼看上去他应该是函数吧,我们跟进去看一下定义是啥:
我的天,他居然是一个宏,他居然不大写。。。看一下后面大写的那个家伙:
他居然是个函数,注意他居然是个全大写的函数,惊不惊喜意不意外,接下来我们作者为啥要这么干。
假如你一直都是些单片机软件,你可能会非常的迷糊,为啥要搞得这么复杂的宏,这里直接告诉你答案,因为要移植,移植,移植,到不同的硬件平台上去,作者写的构架是一个通用的产物,那么不光单片机能用,PC(Linux、windows)都要能用,才是他的目的。
假如换了多年前的我,我会想那么一个平台一个bsp包多么简单,不用那么复杂的宏进行替换,一眼到底多清爽,十几个平台就会有十几个包,修改一点配置也要多一个包,他最终会膨胀到你无法想象的数量,所以兼容这个事情虽然难,也必须要做。
接下来我们总结一下宏,定义一个宏的目的,并不是让你知道他是一个常量或者是一个函数、一段代码,只是通过一个别名告诉你这段代码是干什么用的,他的初衷并不是希望你单步跟进去看看是怎么实现的,而是让你对这段代码整体的功能有个大体的理解。
宏不一定非要大写,函数也不一定非要小写,有些特殊的场景,我们需要忘掉那些脑袋中那些常规的套路。
也就是说一个宏,可以是一个常量,一段代码或者一个函数等等。第二点,宏定义用的是#define进行定义,也就是说宏定义是一个预处理命令,他最终会在真正的编译之前帮你配置出真正需要编译的代码,那个唯一配置的包。
最终作者希望达到的效果是,不管你有多少款板子,多少种配置,基于一个通用的SDK源码包,通过简单的宏定义命令就可以组织出一个你想要的工程。