35

偶尔需要在 C++ 中使用无操作语句。例如,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-effectVisual C++ 警告,它不会针对这种特殊情况发出,但在没有强制转换为void.

它是通用便携的吗?有没有更好的办法?

4

11 回答 11

23

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

#define noop

然后用户代码将具有:

if (condition) noop; else do_something();

您提到的替代方法也是 no-op: (void)0;,但是如果您要在宏中使用它,则应将其留给;调用者添加:

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

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

于 2011-11-02T10:19:44.277 回答
20

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

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

我想编译器可以通过警告您的建议来避免这个问题,(void)0同时只进行((void)0)特殊处理。所以你可能会更好地使用((void)0),但我对此表示怀疑。

通常,将某些东西强制转换为 void,无论有没有额外的封闭括号,惯用的意思是“忽略这个”。例如,在 C 代码中void,为了抑制未使用变量的警告,将函数参数转换为。所以在这个分数上,一个警告的编译器也会相当不受欢迎,因为抑制一个警告只会给你另一个警告。

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

于 2011-11-02T12:35:53.337 回答
10

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

于 2011-11-02T11:07:51.423 回答
8

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

于 2011-11-02T10:18:40.557 回答
4

我参加这个聚会的时间相当晚,但我需要在一个 Arduino 项目中的 loop() 中使用相同的方法,其中所有处理都在定时器中断服务例程 (ISR) 中完成。发现内联汇编代码在没有定义函数的情况下对我有用:

void loop(){
  __asm__("nop\n\t");             // Do nothing.
}
于 2020-01-13T00:55:35.170 回答
3

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

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

于 2018-09-04T14:29:12.253 回答
1

那么:

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

要不就

#define NOP() ({;})
于 2018-04-13T08:14:33.013 回答
0

AFAIK, it is universally portable.

#define MYDEFINE()

will do as well.

Another option may be something like this:

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

However, I'd stick to (void)0 or use intrinsics like __noop

于 2011-11-02T10:21:17.597 回答
0

我建议使用:

static_cast<void> (0)   
于 2014-11-02T03:11:41.347 回答
0

优化不会省略这段代码

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

for (...)
{
    nop();
}
于 2015-11-13T16:34:12.600 回答
-1
    inline void noop( ) {}

自我记录

于 2015-03-22T18:00:22.770 回答