21

I was reading about __noop and the MSDN example is

#if DEBUG
   #define PRINT   printf_s
#else
   #define PRINT   __noop
#endif

int main() {
   PRINT("\nhello\n");
}

and I don't see the gain over just having an empty macro:

#define PRINT

The generated code is the same. What's a valid example of using __noop that actually makes it useful?

R Sahu
  • 204,454
  • 14
  • 159
  • 270
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • I guess there are situations where "no statement" alters how things work. Not entirely sure I can think of one right now tho'. – Mats Petersson Jan 22 '13 at 13:01
  • 2
    Btw, their example is a bit dodgy since it results in an expression with a different type in debug and release mode. But it's not as dodgy as the type in debug mode being whatever the "arguments" to `PRINT` were! Variadic macros allow a better-behaved definition `#define PRINT(...) ((void)printf_s(__VA_ARGS__))` and `#define PRINT(...) ((void)0)`, and that also stops you trying to take a function pointer with `&PRINT`. – Steve Jessop Jan 22 '13 at 13:33

2 Answers2

20

The __noop intrinsic specifies that a function should be ignored and the argument list be parsed but no code be generated for the arguments. It is intended for use in global debug functions that take a variable number of arguments.

In your case the argument is an obviously side effect free expression that can be easily optimized out, so it doesn't matter.

But if the argument expression has side effects or is so complex that the compiler can't prove that it terminates normally and has no side-effects then using __noop prevents the potentially expensive evaluation of that expression.

The second benefit is that it behaves like a function call with a variable number of arguments syntactically. So substituting it for a function call doesn't affect the parsing of the program. With some other replacements (like the empty string), that might be a problem in some situations.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
15
#define PRINT
extern int some_complicated_calculation();
PRINT("%d\n", some_complicated_calculation());

would call the function even though you don't want the result.

Using __noop, the function won't be called.

You could (assuming the compiler supports variadic macros) define PRINT to ignore the arguments; but then they won't be parsed at all, and may become invalid if you change the code around them without compiling the variant that defines PRINT to do something. Using __noop, the arguments are still parsed, so are more likely to remain valid.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644