【C语言内功心法】__weak -- 示弱也是一种强大

何为__weak?

__weak 用于修饰函数,赋予这个函数  的属性。

在使用 STM32 的 hal 库的时候,我们常常可以看到很多库自带的函数有很多是使用 __weak 修饰的,比如:

image-20220911131759212

国内的知名操作系统 RT-Thread 也有大量使用 __weak 这个修饰符。

/* Compiler Related Definitions */
#ifdef __CC_ARM                         /* ARM Compiler */
    #define RT_WEAK                     __weak
#elif defined (__IAR_SYSTEMS_ICC__)     /* for IAR Compiler */
    #define RT_WEAK                     __weak
#elif defined (__GNUC__)                /* GNU GCC Compiler */
    #define RT_WEAK                     __attribute__((weak))
#elif defined (__ADSPBLACKFIN__)        /* for VisualDSP++ Compiler */
    #define RT_WEAK                     __attribute__((weak))
#elif defined (_MSC_VER)
    #define RT_WEAK
#elif defined (__TI_COMPILER_VERSION__)
    #define RT_WEAK
#else
    #error not supported tool chain
#endif

弱是相对的


首先 弱 是相对的,具体弱在哪里?又是和什么比较?

其实函数名称前面加上 __weak 修饰符,我们一般称这个函数为“弱函数”。

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

既是弱肉强食,弱为何能生存?


一般来说,__weak 修饰符的函数是有软件供应商去定义的(比如 ST 提供的库函数),因为会使用到一些回调函数(比如中断回调函数等),所以需要定义该函数,才能在编译的时候不会报错。但是这些函数一般是开发者要使用,如果直接去软件供应商定义的函数里面实现功能,就会造成文件内容耦合,开发者切换平台或者工程时,做的工作量会更大。

所以软件供应商会用 __weak修饰实现函数,目的是保证编译能够正常通过,开发者要使用的时候,可以在自己的文件中再定义该函数,然后在该函数实现自己的功能,此时编译器会忽略 __weak弱化后的函数。当然如果你稍微懒了点,也可以不定义新的函数,用定义好的__weak修饰的函数实现自己的功能,编译器也照收不误。

还有一种情况是如果拿到的程序库的是软件包的格式(看不到源代码的那种),那你就得自己去定义这个同名函数去实现自己的功能。这个功能用处还挺大,笔者就遇到过要给客户提供功能模块代码,由于不能提供源码,只能提供软件包文件(一般格式为 .lib),但是又需要给客户提供调用的接口函数,我在软件包定义的话,客户用不了(因为看不到源码),我不定义的话,编译会报错,客户会怀疑你的工程是不是有问题。此时 __weak 真是应对这种问题的大救星,谁还能说它弱呢?

值得注意之处


从上文中的 RT-Thread 代码可以看到,__weak在不同平台有不同面孔,有些甚至没有,这是因为__weak函数修饰符并不是 C 标准的里面的东西,这意味着:

并不是所有的编译器都支持__weak这个特性,有些小众的编译器还真就不支持,所以使用前请查询相关编译器是否支持。

__weak在所有支持的编译器中面貌长的也一样,详情还是得查询相关编译器。长得不一样对于代码的移植性可是重大的打击,目前比较好的解决办法是:如前面 RT-Thread代码描述那样,用宏定义结合预编译的方式去给不同的 weak定义统一的名字,比如 RT_WEAK。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值