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

三世轮回 提交于 2019-11-27 07:34:08

问题


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):

#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;

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

Is it universally portable? Is there a better way?


回答1:


I suspect that it might trigger warnings on some compilers

Unlikely, since ((void)0) is what the standard assert macro expands to when NDEBUG is 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.

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

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 void in 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.

Note that in C++, standard headers are permitted to include each other. Therefore, if you are using any standard header, assert might 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 could undefine 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 assert in a "universally portable" way, since all C++ implementations already have it, and it doesn't do what you're defining it to do here.




回答2:


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:

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

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




回答3:


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




回答4:


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




回答5:


And what about:

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

or just

#define NOP() ({;})



回答6:


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

I found this question because I needed to do the same thing at global scope, 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 always be a NO-OP.)




回答7:


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




回答8:


I recommend using:

static_cast<void> (0)   



回答9:


    inline void noop( ) {}

Self-documenting




回答10:


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();
}


来源:https://stackoverflow.com/questions/7978620/whats-a-portable-way-to-implement-no-op-statement-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!