什么是在C ++中实现无操作语句的可移植方式?

时间:2011-11-02 10:10:57

标签: c++ noop

有一段时间,需要在C ++中使用无操作语句。例如,实现在非调试配置中禁用的assert()(另请参阅this question):

#ifdef _DEBUG
#define assert(x) if( !x ) { \
                     ThrowExcepion(__FILE__, __LINE__);\
                  } else {\
                     //noop here \
                  }
#else
#define assert(x) //noop here
#endif

到目前为止,我的印象是正确的方法是使用(void)0;进行无操作:

(void)0;

然而我怀疑它可能会在某些编译器上触发警告 - 类似于C4555: expression has no effect; expected expression with side-effect Visual C ++警告,这些警告不是针对此特定情况发出的,而是在没有强制转换为void时发出的。

普遍便携吗?还有更好的方法吗?

11 个答案:

答案 0 :(得分:16)

最简单的无操作只是根本没有代码:

#define noop

然后用户代码将具有:

if (condition) noop; else do_something();

你提到的替代方案也是一个no-op:(void)0;,但是如果要在宏中使用它,你应该将;放在一边让调用者添加:< / p>

#define noop (void)0
if (condition) noop; else do_something();

(如果;是宏的一部分,那么会有额外的;

答案 1 :(得分:15)

  

我怀疑它可能会在某些编译器上触发警告

不太可能,因为((void)0)是标准assert宏扩展到定义NDEBUG时的内容。因此,任何为其发出警告的编译器都会在编译包含断言的代码进行编译时发出警告。我希望用户会将其视为错误。

我认为编译器可以通过警告您的提案(void)0来避免该问题,同时仅对((void)0)进行专门处理。所以你最好使用((void)0),但我对此表示怀疑。

一般情况下,无论有没有额外的封闭的parens,无论是否有这样的东西,都要将某些东西变为无效。例如,在C代码中,将函数参数强制转换为void,以便抑制未使用变量的警告。所以在这个分数上,一个警告的编译器会相当不受欢迎,因为压制一个警告会给你另一个警告。

请注意,在C ++中,允许标准标题彼此包含。因此,如果您使用的是任何标准标头,那么可能已经定义了assert。因此,您的代码在该帐户上是不可移植的。如果您正在谈论“普遍可移植”,则通常应将任何标准头中定义的任何宏视为保留标识符。您可以取消定义它,但为您自己的断言使用不同的名称会更明智。我知道这只是一个例子,但我不明白为什么你想要以“普遍可移植”的方式定义assert,因为所有的C ++实现都已经拥有它,并且它没有做到你的意思我在这里定义它。

答案 2 :(得分:7)

do { } while(0)怎么样?是的,它增加了代码,但我相信今天大多数编译器都能够优化它。

答案 3 :(得分:5)

被视为标准无操作。请注意,编译器可能不会从中生成任何代码。

答案 4 :(得分:2)

在这个聚会上我来晚了,但是我需要一个Arduino项目中的loop()相同,其中所有处理都是在计时器中断服务例程(ISR)中完成的。发现没有定义函数的内联汇编代码对我有用:

void loop(){
  __asm__("nop\n\t");             // Do nothing.
}

答案 5 :(得分:1)

我认为这里的目标以及不将宏定义为空的原因是要求用户添加;。为此,在任何声明合法的地方,都可以使用(void)0(或((void)0)或其他变体)。

我发现了这个问题,因为我需要在 global 范围内做同样的事情,在该范围内,简单的旧声明是非法的。幸运的是,C ++ 11为我们提供了另一种选择:static_assert(true, "NO OP")。可以在任何地方使用它,并且可以达到我在宏后面需要;的目的。 (在我的情况下,宏是用于解析源文件的代码生成工具的标记,因此当将代码编译为C ++时,它总是将成为NO-OP。)

答案 6 :(得分:0)

AFAIK,它具有普遍的便携性。

#define MYDEFINE()

也会这样做。

另一种选择可能是这样的:

void noop(...) {}
#define MYDEFINE() noop()

但是,我会坚持使用(void)0或使用像__noop这样的内在函数

答案 7 :(得分:0)

我建议使用:

static_cast<void> (0)   

答案 8 :(得分:0)

    inline void noop( ) {}

自文档

答案 9 :(得分:0)

优化不会省略此代码

0, 1, 2, 3 ... N - 3, N - 2, N - 1

答案 10 :(得分:0)

那怎么样:

VeriryPermission();

或只是

#define NOP() ({(void)0;})