#ifdef inside #define

103

我正在尝试编写类似于这样的内容:

#define COV_ON(x) \
                #ifdef COVERAGE_TOOL \
                    _Pragma (COVERAGE #x)
                #endif

有没有办法像这样定义COV_ON?我知道我上面所做的是错误的,因为我不能在#define内部使用#ifdef#不是#define中允许的字符)。那么有什么解决方案吗?


1
这里所有的答案似乎都忽略了使用 do {} while(0)(或等效语句)来避免空语句;请参见我在链接的重复问题上的回答 - Roger Lipscombe
6个回答

111

不可能。请反过来做:

#ifdef COVERAGE_TOOL
#define COV_ON(x) _Pragma (COVERAGE #x)
#else
#define COV_ON(x)
#endif

23

简单地将它翻转:

#ifdef COVERAGE_TOOL
#define COV_ON(x) _Pragma (COVERAGE #x)
#else
#define COV_ON(x) /* foo */
#endif

谢谢您的回复。我尝试了COV_ON(on)和COV_ON(off),但是我收到了一个错误,说“错误:期望‘)’,附近为off”。您有关于这个问题的任何想法吗? - agent.smith
它们是字符串。我需要像“on”和“off”一样在引号内使用它们吗? - agent.smith
这取决于你对COVERAGE的定义,但我猜你需要引用它们。我建议你为这个新问题开一个新的提问。 - Philip
我已经尝试过使用引号,但没有用。我已经开了一个新的线程。如果您认为_Pragma的语法有误,请告诉我。 - agent.smith

20

这是一个老问题,但它需要一个最新的答案。

与其在宏内使用行内的ifdef,你可以选择定义一个__VA_ARGS__宏来达到同样的效果。

#ifdef COVERAGE_TOOL
#define IF_COVERAGE_TOOL(...) __VA_ARGS__
#else
#define IF_COVERAGE_TOOL(...)
#endif
#define COV_ON(x) IF_COVERAGE_TOOL( _Pragma (COVERAGE #x) )

这与#ifdef具有类似的功能,但您可以使用括号来划定开始和结束(大多数IDE无法折叠代码)。虽然您仍然可以在上下文中使用#define#ifdef,但不允许使用#include。为了获得类似于#else的内联功能,您可以定义相应的宏,如下所示:

//#define FOO
#ifdef FOO
#define IF_FOO(...) __VA_ARGS__ 
#define NO_FOO(...)
#else
#define IF_FOO(...)
#define NO_FOO(...) __VA_ARGS__
#endif

IF_FOO(
  #define BAR 5
  int foo = BAR;
)
NO_FOO(
  #define foo 5
)

只有NO_FOO()/IF_FOO中的一个会生成代码。

好的,这是个方便的技巧,但我们能不能让它比#ifdefs更加有用呢?也许使用布尔逻辑和配置?让我们设置一些真值表(还有一些帮助宏)。

#define PASTE_(x,y) x##y
#define PASTE(x,y) PASTE_(x,y)
#define PASTE3_(x,y,z) x##y##z
#define PASTE3(x,y,z) PASTE3_(x,y,z)
#define Y(...) __VA_ARGS__
#define N(...)
#define IF(x) x //alternate method similar to IFNOT()

#define NOT_N Y
#define NOT_Y N
#define IF_NOT(x) PASTE(NOT_,x)
#define NOT(x) PASTE(NOT_,x)

#define N_OR_N N
#define N_OR_Y Y
#define Y_OR_N Y
#define Y_OR_Y Y
#define OR(x,y) PASTE3(x,_OR_,y)

#define N_AND_N N
#define N_AND_Y N
#define Y_AND_N N
#define Y_AND_Y Y
#define AND(x,y) PASTE3(x,_AND_,y)

#define N_XOR_N N
#define N_XOR_Y Y
#define Y_XOR_N Y
#define Y_XOR_Y N
#define XOR(x,y) PASTE3(x,_XOR_,y)

#define N_NOR_N Y
#define N_NOR_Y N
#define Y_NOR_N N
#define Y_NOR_Y N
#define NOR(x,y) PASTE3(x,_NOR_,y)

#define N_NAND_N Y
#define N_NAND_Y Y
#define Y_NAND_N Y
#define Y_NAND_Y N
#define NAND(x,y) PASTE3(x,_NAND_,y)

#define N_XNOR_N Y
#define N_XNOR_Y N
#define Y_XNOR_N N
#define Y_XNOR_Y Y
#define XNOR(x,y) PASTE3(x,_XNOR_,y)

#define IF2(x,y,z) PASTE3(x,y,z)

配置文件.h

#define FOO Y
#define BAR N
#define BAZ Y

代码.c

AND(FOO,BAR)(/*do stuff if both FOO and BAR are enabled*/)
IF2(FOO,_AND_,BAR)( /*do stuff if both FOO and BAR are enabled*/ )
OR(BAZ,AND(FOO,BAR))(
  /*do stuff if both FOO and BAR are enabled or BAZ is enabled*/
)

我喜欢你的风格。 - étale-cohomology

6
#ifdef COVERAGE_TOOL
    #define COV_ON(x) _Pragma (COVERAGE #x)
#else
    #define COV_ON(x)
#endif

6
你不能这样做。但你可以交换 #ifdef#define
#ifdef COVERAGE_TOOL
#   define COV_ON(x) _Pragma (COVERAGE #x)
#else
#   define COV_ON(x)
#endif

谢谢您的回复。我尝试了COV_ON(on)和COV_ON(off),但是我收到了一个错误,说期望')',附近为off。对于这个问题有什么想法吗? - agent.smith
不知道你的编译器是什么,我们需要知道预期的 _Pragma 语法是什么;如果没有宏,你会怎么做? - sam hocevar
我正在使用VC2005编译器,看到了在线上的_Pragma语法。我以前从未这样使用过#pragma。 - agent.smith
你需要一个 stringify hack。请参考这个问题和答案 - sam hocevar
我猜问题出在VC2005上。他们不使用_Pragma,而是使用__pragma。我不确定,但看起来是这样。但即便如此,仍然会出现“未知的#pragma”警告和__pragma。 - agent.smith

3

正如您提到的,不可能在#define中使用#ifdef。相反,您应该颠倒顺序:

#ifdef COVERAGE_TOOL \
  #define COV_ON(x) \
    etc.
#endif

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接