函数指针转换为 void 而不被调用

Posted

技术标签:

【中文标题】函数指针转换为 void 而不被调用【英文标题】:Function pointer cast as void without being called 【发布时间】:2020-08-06 00:43:30 【问题描述】:

在阅读一些 STM32 中间件代码时,我遇到了这个非常奇怪的行,无法解析它。基本上是,

(void)(foo);

这不是 void 指针强制转换 - 这很简单。它没有调用函数并将其返回值转换为 void - 这需要更多的括号。它看起来像一个没有左值的右值。这只是防止功能被优化的无操作吗?或者它实际上有什么作用?

这里是上下文。

// SVCCTL_EvtAckStatus_t is just an enum typedef

typedef SVCCTL_EvtAckStatus_t (*SVC_CTL_p_EvtHandler_t)(void *p_evt);

void SVCCTL_RegisterCltHandler( SVC_CTL_p_EvtHandler_t pfBLE_SVC_Client_Event_Handler )

#if (BLE_CFG_CLT_MAX_NBR_CB > 0)
  // Ignore all this
  SVCCTL_CltHandler.SVCCTL_CltHandlerTable[SVCCTL_CltHandler.NbreOfRegisteredHandler] = pfBLE_SVC_Client_Event_Handler;
  SVCCTL_CltHandler.NbreOfRegisteredHandler++;
#else
  // This is the weird stuff
  (void)(pfBLE_SVC_Client_Event_Handler);
#endif

  return;


【问题讨论】:

你有SVC_CTL_p_EvtHandler_t的参考吗?它可能有助于解决此查询。 我认为这里有答案:***.com/questions/34288844。虽然这个问题是针对 C++ 的,但我认为答案也适用于 C。 我的猜测是(1)该行本身是为了抑制关于 pfBLE_SVC_Client_Event_Handler 未被使用的警告,以及(2)正如@augurar 所建议的那样,(void) 是为了抑制一些其他警告。 【参考方案1】:

它什么也不做,除了一件事。阻止编译器抱怨未使用的变量。实际上,在 SO 上,它被推荐为一种可移植的方式:Portable UNUSED parameter macro used on function signature for C and C++

例子:

int somefunction(int a, int b, int c)

    (void)(c); // c is reserved for future usage, 
               //stop the compiler from issuing "unused parameter" warning
    return a+b;

【讨论】:

【参考方案2】:

这是做什么的:

(void)(foo);

将表达式foo 转换为类型void。这是一种表示明确未使用表达式的方式。

如果您查看函数SVCCTL_RegisterCltHandler 的定义,您会发现它接受了一个名为pfBLE_SVC_Client_Event_Handler 的参数。此参数用于#if 预处理器块。如果#if 条件为假,则此参数将未被使用,编译器将发出警告,指出参数pfBLE_SVC_Client_Event_Handler 未使用。

通过将此参数转换为#else 块中的void,它使用该值并消除编译器警告。

【讨论】:

为了迂腐,它将表达式 (foo) 转换为类型 void【参考方案3】:

这是为了防止编译器抱怨 foo 未被使用。字面意思就是这样。这就像 C++ 中的 maybe_unused 属性。

【讨论】:

以上是关于函数指针转换为 void 而不被调用的主要内容,如果未能解决你的问题,请参考以下文章

用于成员函数指针往返转换的 void(*)() 类似物

C++:将派生指针转换为 void 指针,然后转换为抽象指针,并访问成员函数

将 void 指针(数据)转换为函数指针

c# 调用c dll void 指针类型转化问题

如何合法地将函数指针转换为方法指针?

将函数指针的 C 结构体转换为 JNA 代码