views:

676

answers:

3

I have seen debug printfs in glibc which internally is defined as (void) 0, if NDEBUG is defined. Likewise the __noop for Visual C++ compiler is there too. The former works on both GCC and VC++ compilers, while the latter only on VC++. Now we all know that both the above statements will be treated as no operation and no respective code will be generated; but here's where I've a doubt.

In case of __noop, MSDN says that it's a intrinsic function provided by the compiler. Coming to (void) 0 ~ Why is it interpreted by the compilers as no op? Is it a tricky usage of the C language or does the standard say something about it explicity? Or even that is something to do with the compiler implementation?

+7  A: 

(void)0 (+;) is a valid, but 'does-nothing' C++ expression, that's everything. It doesn't translate to the no-op instruction of the target architecture, it's just an empty statement as placeholder whenever the language expects a complete statement (for example as target for a jump label, or in the body of an if clause).

Alexander Gessler
You should note that, used as a macro (say, `#define noop (void)0`), the `(void)` prevents it from being accidentally used as a value (as in `int x = noop;`.
Chris Lutz
Thanks Chris, for clarifying regarding why the type cast to void is made; it prevents from accidental usage of the said noop exp. in expression like assignment, now I did understand.
legends2k
@Chris: Put that as an answer :).
Andrew Aylett
@Andrew: + 1 :)
legends2k
@Andrew - I wish I had, except that I've already hit my rep cap for today. The best I could have hoped for is an accepted answer.
Chris Lutz
@Chris: It's a bit unfair I got the 'accepted' now - but at least you've got an good number of great comment votes, including mine.
Alexander Gessler
@Alexander - You would have had my real upvote, but I ran out of votes several hours ago.
Chris Lutz
+5  A: 

Any expression that doesn't have any side-effects can be treated as a no-op by the compiler, which dosn't have to generate any code for it (though it may). It so happens that casting and then not using the result of the cast is easy for the compiler (and humans) to see as not having side-effects.

anon
+1  A: 

I think you are talking about glibc, not glib, and the macro in question is the assert macro:

In glibc's <assert.h>, with NDEBUG (no debugging) defined, assert is defined as:

#ifdef NDEBUG
#if defined __cplusplus && __GNUC_PREREQ (2,95)
# define __ASSERT_VOID_CAST static_cast<void>
#else
# define __ASSERT_VOID_CAST (void)
#endif
# define assert(expr)           (__ASSERT_VOID_CAST (0))
#else
/* more code */
#endif

which basically means assert(whatever); is equivalent to ((void)(0));, and does nothing.

From the C89 standard (section 4.2):

The header <assert.h> defines the assert macro and refers to another macro,

NDEBUG

which is not defined by <assert.h>. If NDEBUG is defined as a macro name at the point in the source file where <assert.h> is included, the assert macro is defined simply as

#define assert(ignore) ((void)0)

I don't think defining a debug print macro to be equal to (void)0 makes much sense. Can you show us where that is done?

Alok
Yeah, it's glibc and not glib, thanks for notifying; corrected it in the question.
legends2k
http://doc.ddart.net/msdn/header/include/assert.h.html - This is one of the many *assert.h*s I've seen with `(void) 0`.
legends2k
@legends2k: `assert(expr);` is not a debug printing macro. My answer above answers your question about `assert()`.
Alok
@Alok: I agree, it's assert. But the whole doubt was to know more about the `(void) 0` in general as no operation, based on the language or compiler constructs. Thanks!
legends2k