【问题标题】:Using preprocessor conditionals in macro functions with double parentheses在带有双括号的宏函数中使用预处理器条件
【发布时间】:2015-01-28 08:25:19
【问题描述】:

给定:

#define TRACE(x) do { if (DEBUG) dbg_print x; } while (0)

我想要:

TRACE((
    "Message: %s"
#ifdef MYDEF
    "Additional stuff"
#endif
    , msg));

但是报错:

error C2121: '#' invalid character : possibly the result of a macro expansion
error C2146: syntax error : missing ')' before identifier 'ifdef'
error C2121: '#' invalid character : possibly the result of a macro expansion
error C2059: syntax error : ')'

我知道我可以通过编写两个不同的TRACE 调用并使用#ifdef...#else...#endif 轻松解决此问题,但以上只是一个简化的情况。我的实际用例涉及多个控制格式字符串和参数的#ifdef,因此编写多个跟踪调用是不切实际的(例如,使用 3 个ifdef,我需要 2^3 = 8 个不同的调用来处理所有可能的组合)。有没有办法解决这个问题?

【问题讨论】:

  • 应该是dbg_print(x)
  • @BasileStarynkevitch 不,那不是他正在做的事情(见调用,他在那里传递了函数调用的括号)。
  • 这根本不可能。
  • @Axalo 它不是可移植的,但它是可能的。还有一个解决不可移植性的方法。
  • 能否将 TRACE() 宏转换为静态内联函数?

标签: c syntax c-preprocessor preprocessor-directive


【解决方案1】:

有些编译器会通过编译器扩展来编译你的代码,但它是不可移植的。您可以通过有条件地定义另一个宏并将其结果用于调用TRACE 来解决此问题,如下所示:

#ifdef MYDEF
#define IF_MY(x,y) x y
#else
#define IF_MY(x,y) x
#endif

现在你可以写你的TRACE如下:

TRACE((IF_MY("Message: %s", "Additional stuff"), msg));

Demo #1.

它似乎会遇到可扩展性问题。

这种印象是不正确的。您可以轻松地将这种方法扩展到任意数量的变量,而不会遇到组合爆炸。这是添加第二个变量的示例:

#ifdef YOURDEF
#define IF_MY_YOUR(x,y,z) IF_MY(x,y) z
#else
#define IF_MY_YOUR(x,y,z) IF_MY(x,y)
#endif

现在您可以在 TRACE 中使用组合宏:

TRACE((IF_MY_YOUR("Message: %s", "Additional stuff", "More stuff"), msg));

Demo #2 - Both MYDEF and YOURDEF are defined

Demo #2 - Only YOURDEF is defined

Demo #2 - Only MYDEF is defined

Demo #2 - Neither MYDEF or YOURDEF is defined

如果我还有其他要由#define 控制的参数怎么办?

对参数做同样的事情,在xy 部分之间使用逗号。 TRACE 的调用如下所示:

TRACE((
    IF_MY_YOUR_FMT("Message: %s", "Additional %s stuff", "More %s stuff")
,   IF_MY_YOUR_ARG(msg1, msg2, msg3)
));

【讨论】:

  • 感谢您的努力,但它似乎会遇到可伸缩性问题。您的示例仅处理 1 个“附加内容”。如果我有 3 个,每个都由不同的 #define 标志控制怎么办?此外,这仅处理格式字符串。如果我还有其他要由#define 控制的参数怎么办?
  • 等等,IF_MY_YOUR 允许 "y z"、"y" 和 ""(两者都不)的情况。 “z”案怎么样?
  • @wmjdgla 你说得对,我需要把IF_MY 放在两个分支上。查看编辑和四个演示。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-29
  • 1970-01-01
  • 1970-01-01
  • 2011-05-14
  • 1970-01-01
  • 2014-10-01
  • 2013-12-27
相关资源
最近更新 更多