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

sha*_*oth 26 c++ no-op

有一段时间,需要在C++中使用无操作语句.例如,当实现assert()在非调试配置中禁用时(也请参阅此问题):

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

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

(void)0;
Run Code Online (Sandbox Code Playgroud)

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

它普遍便携吗?有没有更好的办法?

Dav*_*eas 18

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

#define noop
Run Code Online (Sandbox Code Playgroud)

然后用户代码将具有:

if (condition) noop; else do_something();
Run Code Online (Sandbox Code Playgroud)

您提到的另一种选择也是无操作:(void)0;但是如果您打算在宏中使用它,您应该留出;一边让调用者添加:

#define noop (void)0
if (condition) noop; else do_something();
Run Code Online (Sandbox Code Playgroud)

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


Ste*_*sop 16

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

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

我想编译器可以通过警告你的提议来避免这个问题,(void)0而只是((void)0)专门处理.所以你可能会更好用((void)0),但我对此表示怀疑.

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

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


Som*_*ude 8

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


ziu*_*ziu 6

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


Mat*_*hew 5

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

我发现这个问题是因为我需要在全局范围内做同样的事情,而普通的旧语句是非法的。幸运的是,C++11 给了我们一个替代方案:static_assert(true, "NO OP"). 这可以在任何地方使用,并实现我需要;宏后的目标。(在我的例子中,宏是解析源文件的代码生成工具的标签,因此当将代码编译为 C++ 时,它始终是 NO-OP。)


小智 5

我在这方面已经很晚了,但我需要在 Arduino 项目中使用相同的循环(),其中所有处理都是在定时器中断服务例程(ISR)中完成的。发现内联汇编代码对我有用,无需定义函数:

void loop(){
  __asm__("nop\n\t");             // Do nothing.
}
Run Code Online (Sandbox Code Playgroud)