假设:
#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个不同的调用来处理所有可能的组合)。有办法解决这个问题吗?
答案 0 :(得分:4)
有些编译器会通过编译器扩展编译代码,但它不可移植。您可以通过有条件地定义另一个宏来解决此问题,并在调用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));
似乎会遇到可扩展性问题。
这种印象不正确。你可以很容易地将这种方法扩展到你想要的任意数量的变量,而不会遇到组合爆炸。以下是添加第二个变量的示例:
#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控制的参数怎么办?
对参数执行相同操作,在x
和y
部分之间使用逗号。 TRACE
的调用如下所示:
TRACE((
IF_MY_YOUR_FMT("Message: %s", "Additional %s stuff", "More %s stuff")
, IF_MY_YOUR_ARG(msg1, msg2, msg3)
));