前言

在 HAL 库中,很多回调函数前面使用__weak 修饰符。

weak 顾名思义是“弱”的意思,所以如果函数名称前面加上__weak 修饰符,我们一般称这个函数为“弱函数”。

加上了__weak 修饰符的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,
那么编译器就会执行__weak 声明的函数,并且编译器不会报错。

举个例子

我们打开工程模板,找到并打开文件stm32f4xx_hal.c 文件,里面定义了一个函数 HAL_MspInit,定义如下:

__weak void HAL_MspInit(void)
{
__IO uint32_t tmpreg = 0x00;
UNUSED(tmpreg);
}

可以看出,HAL_MspInit 函数前面有加修饰符__weak。同时,在该文件的前面有定义函数HAL_Init,并且 HAL_Init 函数中调用了函数 HAL_MspInit。

HAL_StatusTypeDef HAL_Init(void)
{
…//此处省略部分代码
HAL_MspInit();
return HAL_OK;
}

如果我们没有在工程中其他地方重新定义 HAL_MspInit()函数,那么 HAL_Init 初始化函数执行的时候,会默认执行 stm32f4xx_hal.c 文件中定义的 HAL_MspInit 函数,而这个函数没有任何控制逻辑。 如果用户在工程中重新定义函数 HAL_MspInit,那么调用 HAL_Init 之后,会执行用户自己定义的 HAL_MspInit 函数而不会执行 stm32f4xx_hal.c 默认定义的函数。也就是说,表面上我们看到函数 HAL_MspInit 被定义了两次,但是因为有一次定义是弱函数,使用了__weak修饰符,所以编译器不会报错。

总结

__weak 在回调函数的时候经常用到。这样的好处是,系统默认定义了一个空的回调函数,保证编译器不会报错。同时,如果用户自己要定义用户回调函数,那么只需要重新定义即可,不需要考虑函数重复定义的问题,使用非常方便,在 HAL 库中__weak 关键字被广泛使用。

应用

创建一个工程如下: 
在weakTest.c中定义一个weak函数,并且定义一个调用该weak函数的函数

__weak void weakFunctioin(void){    //定义为__weak类型的函数
logInfo("print weakFunction\r\n");
} int weakFunctionTest(unsigned int tst){ logInfo("print A\r\n");
if (tst) {
logInfo("print B\r\n");
weakFunctioin(); //调用函数
logInfo("print C\r\n");
}else{
logInfo("print D\r\n");
}
logInfo("print E\r\n");
return ;
}

在main.c文件中,定义main函数及weakFunctionTest函数:

void weakFunctioin(void){    //定义为正常的函数

    logInfo("print nonWeakFunction\r\n");
return;
} int main(void){ logInit(logLevelDebug);
logInfo("Build @ %s %s,system start\r\n", __DATE__, __TIME__); weakFunctionTest();
logInfo("Build @ %s %s,system stop\r\n", __DATE__, __TIME__);
while();
return ;
}

运行时打印为:

-I: Build @ Jun   ::,system start
-I: print A
-I: print B
-I: print nonWeakFunction
-I: print C
-I: print E
-I: Build @ Jun ::,system stop

参考:

https://blog.csdn.net/baicaiaichibaicai/article/details/73129417?utm_source=blogxgwz1

https://blog.csdn.net/qq562029186/article/details/76216311#

__weak修饰符的更多相关文章

  1. __weak 修饰符

    在 HAL 库中,很多回调函数前面使用__weak 修饰符,这里我们有必要给大家讲解__weak 修饰符的作用. weak 顾名思义是“弱”的意思,所以如果函数名称前面加上__weak 修饰符,我们一 ...

  2. __block和__weak修饰符的区别

    block下循环引用的问题 __block本身并不能避免循环引用,避免循环引用需要在block内部把__block修饰的obj置为nil __weak可以避免循环引用,但是其会导致外部对象释放了之后, ...

  3. __weak与__block修饰符区别

    API Reference对__block变量修饰符的解释,大概意思: 1.__block对象在block中是可以被修改.重新赋值的. 2.__block对象在block中不会被block强引用一次, ...

  4. IOS开发 __weak与__block修饰符到底有什么区别

    API Reference对__block变量修饰符有如下几处解释: //A powerful feature of blocks is that they can modify variables ...

  5. Objective C中的ARC的修饰符的使用---- 学习笔记九

    #import <Foundation/Foundation.h> @interface Test : NSObject /** * 默认的就是__strong,这里只是做示范,实际使用时 ...

  6. [转]黑幕背后的__block修饰符

    http://www.cocoachina.com/ios/20150106/10850.html 我们知道在Block使用中,Block内部能够读取外部局部变量的值.但我们需要改变这个变量的值时,我 ...

  7. ARC下的所有权修饰符

    ARC有效时,id类型必须加上所有权修饰符 下面为三种等效的声明,为了便于和二级指针的情况联系起来,采用第一种. NSError * __weak error = nil; NSError __wea ...

  8. iOS 基础日记-修饰符

    今晚随便温习了一下iOS 基础关于修饰符这块的东西,下面简单的来描述一下,其中有的也是在网络学习到的: strong与weak是由ARC新引入的对象变量属性 ARC的解释:ARC引入了新的对象的生命周 ...

  9. 01 (OC)* @property 后面可以有哪些修饰符?

    一:@property 后面可以有哪些修饰符? 1:线程安全的: atomic,nonatomic 2:访问权限的 readonly,readwrite 3:内存管理(ARC) assign, cop ...

随机推荐

  1. 2015 Multi-University Training Contest 4 hdu 5338 ZZX and Permutations

    ZZX and Permutations Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/O ...

  2. CodeForces 362E Petya and Pipes

    Petya and Pipes Time Limit: 1000ms Memory Limit: 262144KB This problem will be judged on CodeForces. ...

  3. C++函数的导出与导入

    DLL使用 (1)隐式链接到 DLL 的可运行文件在生成时链接到导入库(.lib文件). (2)採用显式连接(LoadLibrary和GetProcAddress)时,不须要.lib文件. 函数导出方 ...

  4. 2)Win10-UWA开发 API參考 - 1

    孙广东  2015.8.23 大多数 Windows 执行时 API 如今适用于 Windows Phone 应用商店应用以及 Windows 应用商店应用,这意味着当你创建同一时候面向 Window ...

  5. node 内存消息队列

    var net = require('net') var clients = [] ,msgs = {} function unWrapMsg(data){ data = data.toString( ...

  6. HDU 1040.As Easy As A+B【排序】【如题(水!水!水!)】【8月24】

    As Easy As A+B Problem Description These days, I am thinking about a question, how can I get a probl ...

  7. EF的CRUD

    已经知道EF就是一个能够使得编程人员用面向对象的思想操作数据库的框架,那么在最初学习SQL的时候我们就知道对数据库的操作就是增删改查.万变不离其宗. EF也是操作数据库的当然也就是要对数据库实现增删改 ...

  8. bzoj1082: [SCOI2005]栅栏(二分答案搜索判断)

    1082: [SCOI2005]栅栏 题目:传送门 题解: 是不是一开始在想DP?本蒟蒻也是qwq,结果很nice的错了ORZ 正解:二分+搜索 我们可以先把两种木材都进行排序,那么如果需要的最大木材 ...

  9. iOS CoreData 介绍和使用(以及一些注意事项)

    iOS CoreData介绍和使用(以及一些注意事项) 最近花了一点时间整理了一下CoreData,对于经常使用SQLite的我来说,用这个真的有点用不惯,个人觉得实在是没发现什么亮点,不喜勿喷啊.不 ...

  10. Opencv Mat矩阵中data、size、depth、elemSize、step等属性的理解

    data: uchar类型的指针,指向Mat数据矩阵的首地址.可以理解为标示一个房屋的门牌号: dims: Mat矩阵的维度,若Mat是一个二维矩阵,则dims=2,三维则dims=3,大多数情况下处 ...