首先我们看一下STM32的HAL库中的代码
代码库中的__weak就是我们今天要谈关键字,这其实不是C语言的关键字,而是一个编译器的关键字。__weak关键字源自于C++,后来被ARMCC以及gcc for arm等编译器实现。
在C语言中,函数和初始化的全局变量(包括显示初始化为0)是强符号,未初始化的全局变量是弱符号。对于强弱符号,有下列三条规则适用:
① 同名的强符号只能有一个,否则编译器报"重复定义"错误。
② 允许一个强符号和多个弱符号,但定义会选择强符号的。
③ 当有多个弱符号相同时,链接器选择占用内存空间最大的那个。
对于C语言来说,编译器默认函数和初始化了的全局变量为强符号,未初始化的全局变量为弱符号(C++并没有将未初始化的全局符号视为弱符号)。我们也可以通过GCC的"__attribute__((weak))"来定义任何一个强符号为弱符号 ,ARMCC中可以直接使用“__weak”。
int weak1; int strong = 1; int __attribute__((weak)) weak2 = 2; int main() { return 0; }
上面这段程序中,"weak"和"weak2"是弱符号,"strong"和"main"是强符号 。
那么这个__weak有什么作用呢?首先说他在STM32的HAL库中修饰的是一个Callback函数,其实就是一个回调函数,用__weak修饰后就是告诉编译器,此函数是一个弱函数,如果编译器找不到一个同名的强函数,那么就调用这个弱函数的实现执行相应弱函数里面的程序。加入用户使用同样的函数名实现了一个强函数,则编译器会优先使用用户自定义的强函数进行连接。
现在是不是很清楚了,他实际上就是为用户调用或者二次开发提供了便利,有点OOP中的虚函数的感觉。
其实在另一个例子中我们也会遇到他的一些应用,比如我们常用的printf函数,做单片机开发的时候,经常使用这个函数来将字符串通过串口打印,大家都会遇到一个fput函数的重定向。为什么要重定向呢?
原因是C语言的库函数实现的printf函数最终是去调用fput函数显示在终端上,在系统函数库中,这个fput就是被__weak修饰的,因此我们就是靠重新实现fput函数来实现将原本打印在终端上的字符串从串口的sendchar函数输出。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...