宏上的空括号有什么作用?

What do empty parenthesis on a macro achieve?

我在 C 中遇到了一个我无法解决的宏。我感到困惑的一点是宏名称末尾的附加括号 myTEST_MARK()。这实际上有什么作用还是只是一种命名约定?

#ifndef myTEST_FLAG
    #define myTEST_FLAG()
#endif

…

//usage:

if (condition) {
    do something 
} else {
   myTEST_FLAG();
}

我了解有关文本替换和设置的基础知识markers/flags,也许#defines 在这里可以帮助稍后进行调试?

宏可以有参数,因为它们实现了某种内联功能。带有空括号的宏只是模拟一个 void 函数。

但是为什么要这样定义一个空的宏呢?

通常这样做是为了进行预编译级别的设置。像

#ifdef SOME_CONFIG_TAG_ENABLED
  #define myTEST_FLAG() doSomething()

#else
  #ifndef myTEST_FLAG
    #define myTEST_FLAG()
  #endif
#endif
…

//usage:

if (condition) {
    do something 
} else {
   myTEST_FLAG();
}

用法保持不变,但如果在某处定义了SOME_CONFIG_TAG_ENABLED(在某些config.h包含文件中或通过-D编译器选项)执行anc实际操作,否则为发表评论 没有改变来电者。

请注意,在启用部分您不仅可以拥有另一个宏,而且还可以拥有在某些情况下可能想要完全禁用的功能。一个常见的例子可能是:

// In .c:
#ifdef STATUS_DEBUG_ENABLED
void TraceStatus(void)
{
  // a lot of printfs tracing the "status"
}
#endif

...

// In .h:
#ifdef STATUS_DEBUG_ENABLED
void TraceStatus(void);
#else
  #define TraceStatus()
#endif

...

// Usage:
if (condition) {
    do something 
} else {
   TraceStatus();
}

通过这种方式,您可以轻松编译一个调试版本,启用您可能希望在生产版本中删除的所有日志。

用括号定义的宏是"function-like"宏。没有参数的宏的出现将不会被识别和扩展。

定义不带参数的类函数宏而不是类对象宏有多种原因。

一个原因是我们预计将来会有争论。如果我们更改宏,使其接受一个或多个参数,那么编译器诊断将找到所有调用宏的地方,而没有参数。如果我们更改一个类似对象的宏,使其现在接受参数,则不会诊断现有调用;他们只是默默地停止扩张。

另一个原因是宏提供了一个函数抽象,并且可以被一个不带参数的真实函数所取代。我们希望能够通过删除宏来做到这一点,而不必编辑所有调用来添加括号。

一致性发挥了作用。如果宏是构成接口的一组相关宏的一部分,并且其中一些有参数,则无参数的宏应该与其他宏类似。

另一个原因是宏扩展做了一些有副作用的事情。看起来像 foo; 的宏调用看起来无害。如果它改变了一个全局变量的值或执行I/O,它看起来太无害了;如果电话看起来像 foo();,那么它理所当然地看起来更可疑。如果我们将副作用塞进一个看起来像 foo; 的表达式中,那么我们就是在使用预处理器将 C 语言转换成另一种语言,当简单的替代方案允许我们避免它时,不应该这样做。