首页 > 解决方案 > c中的多行宏(#if-#endif)

问题描述

我的代码:

#define DEBUG 3
#define TEST(...) 
    #if (DEBUG == 3) \
        printf("%s: %s\n", __FILE__, __VA_ARGS__); 
    #endif 

int main(void) {

    TEST("TEST")

    return 0;
}

错误:在标记“printf”之前缺少二元运算符。

我不明白有什么问题

标签: cmacrosmultiline

解决方案


您试图将#if宏放入内部,但 C 不允许这种事情。它失败的原因是printf #if 内部是意外的。这是一个常见的请求,但它是不允许的。

但是,您可以通过更改测试方式来完成同样的事情:

#include <stdio.h>

#define DEBUG 3

#if (DEBUG == 3)
# define TEST(...) printf("%s: %s\n", __FILE__, __VA_ARGS__);
#else
# define TEST(...)
#endif

int main(void) {

   TEST("TEST")

   return 0;
}

编辑:虽然像这样的测试类型的宏很常见,但这不是一个很好的方法,因为它可能导致调试/非调试情况下的不愉快的意外。

在这种情况下会发生什么?

   if (something)
       TEST("blah")
   else
       TEST("no")

这在调试模式下可以按您的预期工作,但甚至不会在生产中编译,因为它会演变为if (something) else- 它甚至没有结束分号。很容易找到其他更狡猾的例子。

像这样在宏中隐藏分号通常是在自找麻烦,因此更好的方法是让它们具有类似功能,您必须自己提供分号,最明显的方法是:

#  #define TEST(...) printf("%s: %s\n", __FILE__, __VA_ARGS__) // no semicolon

...
    if (something)
        TEST("blah");
    else
        TEST("no");

这样会更好,并且不会引起意外,但它仍然有点麻烦,因为它可能会留下一个悬空的分号,一些编译器对此表示反对。

对此的修复可以是:

#if (DEBUG == 3)
# define TEST(...) printf("%s: %s\n", __FILE__, __VA_ARGS__)
#else
# define TEST(...) ((void)0)  // dummy statement
#endif

这至少使编译器安静下来。这里也有其他方法。


推荐阅读