函数指针在未被调用的情况下转换为 void

Function pointer cast as void without being called

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

(void)(foo);

这不是空指针转换 - 这很简单。它不是调用函数并将其 return 值转换为 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;
}

它什么都不做,除了一件事。阻止编译器抱怨未使用的变量。它实际上被推荐在这里,在 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;
}

这是做什么的:

(void)(foo);

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

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

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

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