如果条件为假,则无操作的函数式宏

Function-style macro with no-op if a condition is false

假设我在我的代码中的多个地方有以下构造并且想让我的代码更清晰:

#if HAVE_LIBFOOBAR
    foobar_func(data);
#endif

我正在考虑围绕这个编写一个函数样式的宏,它将处理条件,使代码中的出现看起来像一个常规函数调用:

    foobar_func_if_available(data)

如果条件为真,这将被替换为对实际函数的调用,否则它将是空操作。

因此,类似于:

#if HAVE_LIBFOOBAR
#define foobar_func_if_available(x) foobar_func(x)
#else
#define foobar_func_if_available(x) {}
#endif

问题:

编辑:有人认为这是 another question 的重复,但我认为不是:另一个问题问“这个构造解决了什么问题”,我的是“什么构建将解决我的问题”。确实另一个问题对我的问题有可能的解决方案,它没有涵盖我问题的所有方面。

你无法通过单个 #define 实现它。

您不需要 {} 作为空操作,您可以通过多种方式定义空表达式:

#define foobar_func_if_available(x)
#define foobar_func_if_available(x) ;
#define foobar_func_if_available(x) do{}while(0)

在某些情况下,这些中的任何一个都可能导致语法问题,但对于 void 函数,这两种情况都不太可能导致问题 - 但是,对于非 void 函数,解决方案会失败。

完全避免类函数宏的更好解决方案是有条件地定义函数体:

void foobar_func( int n )
{
    #if defined HAVE_LIBFOOBAR
       // do something
    #else
       // do nothing
    #endif
}

空函数是否导致没有代码是编译器和应用的优化级别的问题,但重要的是代码将在对 foobar_func() 的调用有效的所有情况下在语法上工作。担心它是不是空操作可能是一件小事。

创建一个虚拟函数并使#define 指向它(有条件地):


#if HAVE_LIBFOOBAR
  #define foobar_func_if_available(x) foobar_func(x)
#else
  int dummy(int ignored)
  {
  return 0;
  }
  #define foobar_func_if_available(x) dummy(x)
#endif

或者只是:

#define foobar_func_if_available(x) 0

((int)0)((void)0) 这样的宏可能是最多的 flexible/safest 无操作宏。它们很灵活,因为您可以使用它们 在表达式中(不像 do{}while(0))并且它们不会像 {}; 那样破坏 if-else

示例 {}(或 ;)宏如何破坏 if-else:

#define foo() {}
if(1) foo(); else bar(); //syntax error because if(1) {}; else bar(); was pasted

如果宏应该模拟一个整数返回函数,最好在普通整数常量上使用强制转换的整数文字,因为整数常量(尤其是零)可用于更多上下文(大小写标签、位域大小、数组大小) ,空指针常量)比非常量整数表达式。

您不需要有两个宏,如:

#if HAVE_LIBFOOBAR
    #define foobar_func_if_available(x) foobar_func(x)
#else
    #define foobar_func_if_available(x) ((void)0) /*if foobar_func returns void*/
#endif

你可以把条件放在宏里面:

#define foobar_func_if_available(x) \
    (HAVE_LIBFOOBAR?foobar_func(x):((void)0))

即使是非常愚蠢的编译器也应该能够优化常量条件输出。

但是如果你依赖一个空的 HAVE_LIBFOOBAR#if 中评估为 0,那么上面的方法将不起作用 - HAVE_LIBFOOBAR 将需要一个整数。

( 你可以做

#if !HAVE_LIBFOOBAR
    #undef HAVE_LIBFOOBAR
    #define HAVE_LIBFOOBAR 0
#endif
#define foobar_func_if_available(x) \
        (HAVE_LIBFOOBAR?foobar_func(x):((void)0))

将空的 HAVE_LIBFOOBAR 规范化为 0,但除非您将重用现在确定的 HAVE_LIBFOOBAR 的定义,否则这似乎是对原始两个 [=30] 的不必要的复杂化=] 宏。 )