在 C++ 中实现 no-op 语句的可移植方式是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7978620/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:49:50  来源:igfitidea点击:

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

c++noop

提问by sharptooth

One in a while there's a need for a no-op statement in C++. For example when implementing assert()which is disabled in non-debug configuration (also see this question):

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

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

So far I'm under impression that the right way is to use (void)0;for a no-op:

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

(void)0;

however I suspect that it might trigger warnings on some compilers - something like C4555: expression has no effect; expected expression with side-effectVisual C++ warning that is not emitted for this particular case but is emitted when there's no cast to void.

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

Is it universally portable? Is there a better way?

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

采纳答案by Steve Jessop

I suspect that it might trigger warnings on some compilers

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

Unlikely, since ((void)0)is what the standard assertmacro expands to when NDEBUGis defined. So any compiler that issues warnings for it will issue warnings whenever code that contains asserts is compiled for release. I expect that would be considered a bug by the users.

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

I suppose a compiler could avoid that problem by warning for your proposal (void)0while treating only ((void)0)specially. So you might be better off using ((void)0), but I doubt it.

我想编译器可以通过警告您的建议(void)0同时仅进行((void)0)特殊处理来避免该问题。因此,您最好使用((void)0),但我对此表示怀疑。

In general, casting something to void, with or without the extra enclosing parens, idiomatically means "ignore this". For example in C code that casts function parameters to voidin order to suppress warnings for unused variables. So on that score too, a compiler that warned would be rather unpopular, since suppressing one warning would just give you another one.

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

Note that in C++, standard headers are permitted to include each other. Therefore, if you are using anystandard header, assertmight have been defined by that. So your code is non-portable on that account. If you're talking "universally portable", you normally should treat any macro defined in any standard header as a reserved identifier. You couldundefine it, but using a different name for your own assertions would be more sensible. I know it's only an example, but I don't see why you'd ever want to define assertin a "universally portable" way, since all C++ implementations already have it, and it doesn't do what you're defining it to do here.

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

回答by David Rodríguez - dribeas

The simplest no-op is just having no code at all:

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

#define noop

Then user code will have:

然后用户代码将具有:

if (condition) noop; else do_something();

The alternative that you mention is also a no-op: (void)0;, but if you are going to use that inside a macro, you should leave the ;aside for the caller to add:

您提到的替代方法也是一个 no-op: (void)0;,但是如果您打算在宏中使用它,您应该留出;一旁给调用者添加:

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

(If ;was part of the macro, then there would be an extra ;there)

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

回答by Some programmer dude

How about do { } while(0)? Yes it adds code, but I'm sure most compilers today are capable of optimizing it away.

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

回答by ziu

; is considered as standard no-op. Note that it is possible that the compiler will not generate any code from it.

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

回答by ViaExplore - Tomas Kamenicky

And what about:

还有:

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

or just

要不就

#define NOP() ({;})

回答by Matthew

I think the objective here, and the reason not to define the macro to nothing, is to requirethe user to add a ;. For that purpose, anywhere a statementis legal, (void)0(or ((void)0), or other variations thereupon) is fine.

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

I found this question because I needed to do the same thing at globalscope, where a plain old statement is illegal. Fortunately, C++11 gives us an alternative: static_assert(true, "NO OP"). This can be used anywhere, and accomplishes my objective of requiring a ;after the macro. (In my case, the macro is a tag for a code generation tool that parses the source file, so when compiling the code as C++, it will alwaysbe a NO-OP.)

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

回答by Ray McCoy

I'm rather late to the party on this one but I needed the same for a loop() in an Arduino project where all processing is done in timer interrupt service routines (ISR). Found the inline assembler code worked for me without defining a function:

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

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

回答by mloskot

AFAIK, it is universally portable.

AFAIK,它是普遍便携的。

#define MYDEFINE()

will do as well.

也会这样做。

Another option may be something like this:

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

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

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

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

回答by iperov

this code will not omitted by optimization

这段代码不会被优化遗漏

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

for (...)
{
    nop();
}

回答by MattP

I recommend using:

我建议使用:

static_cast<void> (0)