#if 0作为定义

时间:2010-02-09 21:42:41

标签: macros c-preprocessor

我需要一种方法来定义FLAGS_IF宏(或等效物),以便

FLAGS_IF(expression)
<block_of_code>
FLAGS_ENDIF

在调试中编译时(例如使用特定的编译器开关)编译为

if (MyFunction(expression))
{
    <block_of_code>
}

而在发布中不会产生任何指令,就像它是这样的

#if 0
    <block_of_code>
#endif

由于我对 C / C ++预处理器问题的无知,我想不出任何天真的方式(因为#define FLAGS_IF(x) #if 0甚至没有编译)这样做,你能帮忙吗?

我需要一个解决方案:

  • 如果*/
  • 中存在<block_of_code>,则不会搞砸
  • 即使在任何深度的内联函数内,也一定会在发布中生成0条指令(我想这会将if (false){<block_of_code>}排除在外吗?)
  • 尽可能符合标准

6 个答案:

答案 0 :(得分:30)

宏非常邪恶,但没有什么比使用宏来模糊控制语句和块更邪恶了。编写这样的代码是没有充分理由的。做到这一点:

#ifdef DEBUG
  if (MyFunction(expression))
  {
    <block_of_code>
  }
#endif

答案 1 :(得分:12)

以下应该做你想做的事:

#ifdef DEBUG
# define FLAGS_IF(x) if (MyFunction((x))) {
# define FLAGS_ENDIF }
#else
# define FLAGS_IF(x) if(0) {
# define FLAGS_ENDIF }
#endif

if(0)应该变成没有指令,或者至少在大多数编译器中都这样做。

编辑:Hasturkun评论说您并不真正需要FLAGS_ENDIF,因此您可以改为编写代码:

FLAGS_IF(expression) {
   <block_of_code>
}

使用以下宏:

#ifdef DEBUG
# define FLAGS_IF(x) if (MyFunction((x)))
#else
# define FLAGS_IF(x) if(0)
#endif

答案 2 :(得分:7)

我可能会这样做:

#ifdef DEBUG
const bool IS_RELEASE_MODE = false;
#else
const bool IS_RELEASE_MODE = true;
#endif

if (IS_RELEASE_MODE && MyFunction(expression))
{
    ...
}

这应该从发布版本中编译出来,因为if(false&amp;&amp; f())与if(false)相同,后者在大多数编译器中得到优化。

如果您坚持不在代码内部使用#ifdef,那就是这样。否则,我更喜欢其他人发布的#ifdef DEBUG if(MyFunction(expression)){...} #endif。

答案 3 :(得分:4)

为什么不能使用以下内容?

#ifdef DEBUG
code for debug mode
#else
code for release mode
#endif

答案 4 :(得分:3)

我通常尽可能避免过多使用条件编译。

首先,它通常是丑陋的,不太可读。

但更重要的是,当项目使用条件编译来打开调试代码时,&amp;我有时会遇到调试代码在禁用时变得陈旧的问题。然后当我想实际使用它调试代码时,我打开它......事情。别。建立。了。

调试代码可能会引用不再存在的变量或函数,或者潜在调试代码周围的事情已经发生了足够的变化,以至于它在语法上不再有效。

这可能真的很烦人。

所以我个人采取了避免条件编译来启用/禁用调试代码,转而使用枚举或宏(仍然有条件地编译)作为if语句中的条件。编译为if (0)时,不会生成任何运行时代码 - 完全符合要求。但是,代码仍然经过编译和语法检查,所以它始终至少在语法上是正确的。

#if NDEBUG  // using the same standard macro that `assert()` uses
            //  use your own if NDEBUG doesn't make sense
enum {
    DebugOn = 0
}
#else
enum {
    DebugOn = 1
}
#endif


// ... elsewhere

if (DebugOn) {
    // this always gets compiled, but if it's a release build
    //  the compiler will not emit anything...
}

作为FryGuy mentioned,如果您愿意,可以轻松地将其与调用MyFunction()结合起来 - 在发布版本中,由于短路而不会调用该函数,这是您指定的行为:

if (DebugOn && MyFunction( expression)) {
    // this always gets compiled, but if it's a release build
    //  the compiler will not emit anything...
}

但就个人而言,我可能会使用

if (DebugOn) {
    if (MyFunction( expression)) {
        // ... 
    }
}

我认为有助于更清楚地说明(仅仅是一点点)这是一个仅调试的块。

这样做的好处是总是被编译并且没有隐藏在宏后面的流量控制(其他几个答案已经提到它是邪恶的)。

答案 5 :(得分:2)

这样的事情怎么样:

#ifdef DEBUG
#define FLAGS_IF(expr, block) { if (MyFunction(expr)) block }
#else
#define FLAGS_IF(expr, block)
#endif

你可以像这样使用它:

FLAGS_IF(your_favourite_expression,
  ({
     // some code
  })
)