在带双括号的宏函数中使用预处理器条件
Using preprocessor conditionals in macro functions with double parentheses
鉴于:
#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 个不同的调用照顾所有可能的组合)。有解决办法吗?
一些编译器会通过编译器扩展来编译你的代码,但它是不可移植的。您可以通过有条件地定义另一个宏并在调用 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));
it seems like it will run into scalability issues.
这种印象是不正确的。您可以很容易地将这种方法扩展到任意数量的变量,而无需 运行 组合爆炸。这是添加第二个变量的示例:
#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
What if I have additional arguments that are to be controlled by #define too?
对参数做同样的事情,在 x
和 y
部分之间用逗号分隔。 TRACE
的调用如下所示:
TRACE((
IF_MY_YOUR_FMT("Message: %s", "Additional %s stuff", "More %s stuff")
, IF_MY_YOUR_ARG(msg1, msg2, msg3)
));
鉴于:
#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 个不同的调用照顾所有可能的组合)。有解决办法吗?
一些编译器会通过编译器扩展来编译你的代码,但它是不可移植的。您可以通过有条件地定义另一个宏并在调用 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));
it seems like it will run into scalability issues.
这种印象是不正确的。您可以很容易地将这种方法扩展到任意数量的变量,而无需 运行 组合爆炸。这是添加第二个变量的示例:
#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
What if I have additional arguments that are to be controlled by #define too?
对参数做同样的事情,在 x
和 y
部分之间用逗号分隔。 TRACE
的调用如下所示:
TRACE((
IF_MY_YOUR_FMT("Message: %s", "Additional %s stuff", "More %s stuff")
, IF_MY_YOUR_ARG(msg1, msg2, msg3)
));