15

维基百科说:

弱符号表示链接可执行和可链接格式 (ELF) 对象文件期间的特殊注释符号。默认情况下,没有任何注释,目标文件中的符号是强的。在链接期间,强符号可以覆盖同名的弱符号。相反,共享名称的两个强符号在链接时会产生链接错误。链接二进制可执行文件时,弱声明符号不需要定义。相比之下,(默认情况下)声明的没有定义的强符号会触发未定义的符号链接错误。C 或 C++ 语言标准未提及弱符号;因此,将它们插入代码不是很便携。即使两个平台支持将符号标记为弱的相同或相似语法,语义也可能在细微之处有所不同,例如

什么是弱功能,它们的用途是什么?我正在使用 stm32f429 微控制器。库中有一些弱函数。但我无法理解,它们和它们的用途!

我在谷歌上搜索了它,但没有得到满意的答案。

4

4 回答 4

35

当函数前面带有描述符 __weak 时,它基本上意味着如果您(编码器)不定义它,则在此处定义它。

让我们看看我的宿敌“HAL_UART_RxCpltCallback()”。

该函数存在于 STM32F4-HAL 代码库的 HAL 中,您可以从 ST-Micro 下载该代码库。

在文件 stm32f4xx_hal_uart.c 文件中,您会发现此函数定义为:

__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  /* NOTE: This function Should not be modified, when the callback is needed,
       the HAL_UART_RxCpltCallback could be implemented in the user  file
  */
}

因此,正如此处代码中的注释所说,将此函数放在您自己的用户文件中。但是,当您这样做时,请不要输入该__weak术语。这意味着链接器将采用您对 HAL_UART_RxCpltCallback() 函数的定义,而不是在 stm32f4xx_hal_uart.c 文件中定义的函数。

这使通用代码库能够始终编译。您不必编写一大堆您不感兴趣的函数,但它会编译。当需要编写自己的代码时,您只需不要将自己的定义为__weak并编写它。

简单的?有帮助吗?

干杯!!

于 2016-02-21T21:30:52.737 回答
3

__weak 函数是可以被同名用户函数覆盖的方法,用于定义向量表和默认处理程序

普通函数编写(声明和定义)被认为是强函数名不能重新声明,你会得到编译器/链接器错误

将函数声明为 week 它可以被用户代码覆盖

void USART1_IRQHandler (void) __attribute__ ((weak, alias("Default_Handler")));

uint32_t vectors[75] __attribute__((section(".isr_vector")));

vectors[0] = STACK_START;
vectors[52] = USART1_IRQHandler;

void Default_Handler(void) {
  while(1);
}


uart1.c (user code)

void USART1_IRQHandler(){
    ...
}

在上面的示例代码中,USART1_IRQHandler 被定义为弱函数并别名为 Default_handler

如果用户在 uart1.c 中定义 USART1_IRQHandler,则用户可以使用相同的名称覆盖此函数而不会出现任何编译器/链接器错误,将使用此新函数定义

于 2021-03-26T14:44:55.190 回答
2

假设我们有一个通用(库)协议接口protocol.c,并且在接收到数据后,我们希望在我们的通信接口中执行应用程序特定的逻辑com.c。这可以通过弱函数来解决。

/// protocol.h
void protocol_recCallback(protocol_t *prt);

/// protocol.c
__weak void protocol_recCallback(protocol_t *prt) {}

void protocol_rx(protocol_t *prt)
{
  // Common protocol interface
  protocol_recCallback(prt);  // This will call application specific function in com.c
}

/// com.c
#include "protocol.h"

void protocol_recCallback(protocol_t *prt)
{
  // Application specific code is executed here
}

优点: 如果protocol_recCallback()没有在com.c. 链接器不会输出未定义的引用,并且__weak会调用该函数。

于 2021-11-24T09:05:55.793 回答
1

In addition to "This gives the generic code base the ability to always compile." __weak allows you to regenerating(in CubeMX) your code without touching your __weak +less callback function code. if you write your code in this:

__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  /* NOTE: This function Should not be modified, when the callback is needed,
       the HAL_UART_RxCpltCallback could be implemented in the user  file
  */
}

and regenarate in cubemx for some reason. Your code will blow up!

于 2021-03-22T14:57:53.600 回答