在C++中实现无操作语句的便携式方法是什么?

What's a portable way to implement no-op statement in C++?

本文关键字:便携式 方法 是什么 语句 操作 C++ 实现      更新时间:2023-10-16

在C++中偶尔需要一个no-op语句。例如,当实现在非调试配置中禁用的assert()时(另请参阅此问题(:

#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时发出的。

它是普遍可移植的吗?有更好的方法吗?

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

#define noop

然后用户代码将具有:

if (condition) noop; else do_something();

您提到的另一种选择也是no-op:(void)0;,但如果您要在宏中使用它,则应该将;放在一边,让调用者添加:

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

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

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

不太可能,因为((void)0)是定义NDEBUG时标准assert宏扩展到的内容。因此,每当编译包含断言的代码以供发布时,任何为其发出警告的编译器都会发出警告。我预计用户会认为这是一个错误。

我想编译器可以通过为您的提案(void)0发出警告来避免这个问题,同时只特别处理((void)0)。所以你最好使用((void)0),但我对此表示怀疑

通常,将某物强制转换为void,无论是否使用额外的封闭parens,其惯用含义都是"忽略此项"。例如,在C代码中,它将函数参数强制转换为void,以抑制对未使用变量的警告。因此,在这一点上,发出警告的编译器也相当不受欢迎,因为抑制一个警告只会给你另一个警告。

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

do { } while(0)怎么样?是的,它添加了代码,但我相信现在大多数编译器都能够对其进行优化。

;被视为标准no-op。请注意,编译器可能不会从中生成任何代码。

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

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

我来晚了,但在Arduino项目中的loop((中,所有处理都是在定时器中断服务例程(ISR(中完成的。发现内联汇编程序代码在没有定义函数的情况下对我有效:

void loop(){
  __asm__("nopnt");             // Do nothing.
}

我建议使用:

static_cast<void> (0)   

关于

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

或者只是

#define NOP() ({;})

AFAIK,它是通用的可移植性。

#define MYDEFINE()

也一样。

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

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

然而,我会坚持使用(void)0或使用像__noop 这样的内部函数

    inline void noop( ) {}

自记录

优化不会省略此代码

static void nop_func()  {   }
typedef void (*nop_func_t)();
static nop_func_t nop = &nop_func;
for (...)
{
    nop();
}

有很多方法,下面是我在MSVS2019Cpp编译器中对其中一些方法进行的比较。

__asm {
        nop
       }

拆卸时转换为nop操作,需要1个机器循环。CCD_ 26生成一些指令。简单的;不会生成任何内容。