15

On my implementation of C++ (Visual Studio 2008 implementation) I see the following line in <cassert>

#ifdef  NDEBUG
#define assert(_Expression) ((void)0)

I do not understand the need to cast 0 to void. It seems to me that

#ifdef  NDEBUG
#define assert(_Expression) (0)

or even simply

#ifdef  NDEBUG
#define assert(_Expression) 0

would do, considering the contexts in which assert(expr) can be used.

So, what's the danger of 0 of type int instead of 0 of type void in this case? Any realistic examples?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • As an aside, while this might seem like a trivial question to many, this is a topic that I've actually had less experienced programmers ask about occasionally. It's similar to (but not a duplicate of) questions about why macros are often wrapped in `do ... while(0)` constructs. Sometimes one person's 'too obvious to be bothered with' is another person's 'WTF?!?'. – Michael Burr Aug 11 '11 at 16:14

1 Answers1

24

The only purpose of the complicated expression (void)0 is to avoid compiler warnings. If you just had a naked, useless expression, the compiler might warn about an expression that has no effect. But by explicitly casting something to void you indicate that you mean to do this.

(Think about how confusing it would be to the user if the compiler suddenly said, "Warning: expression 0; has no effect.", when all you've done is switched to release mode.)

This was also common practice in C, where you'd say (void)printf("Hello"); to tell the compiler that you intentionally chose to ignore the return value of the function.

The (void) cast is not merely a choice by a particular implementation; it's required by the C standard. Quoting the 2011 ISO C standard (similar wording appears in the 1990 and 1999 editions):

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)

The C++ standard requires the contents of the <cassert> header to be the same as the Standard C <assert.h> header.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 11
    There is another reason to do this in the context of `assert`: it ensures that "`foo = assert(blurf);`" provokes a compile-time error in both debug and release modes. – zwol Aug 09 '11 at 20:50
  • 1
    Curiosum: In GCC in C++ mode, we have `static_cast`. Tidy. – Kerrek SB Aug 09 '11 at 20:53
  • It's correct that it generates no code and also suppresses warning, but the real question is why not just `#define assert(ignore)`. My only guess is that some compilers don't like empty statements. – Gene Bushuyev Aug 09 '11 at 20:54
  • @Gene: Same reason as what Zack said - it prevents misuse of the assert statement, and it avoids warnings about naked semicolons. – Kerrek SB Aug 09 '11 at 20:55
  • @Kerrek - *naked semicolons* :) are not suppose to generate warnings, they are common, e.g. `for(; something; something);` – Gene Bushuyev Aug 09 '11 at 21:02
  • @Gene: Depends on your compiler -- I'm pretty sure I've seen plenty of warnings for such constructions, depending on how petty you make your compiler. Point is, why should the assert macro cause noise if it could easily avoid it? – Kerrek SB Aug 09 '11 at 21:03
  • @Kerrek - `f(assert(1==0));` ? that will fail in debug mode anyway. – Gene Bushuyev Aug 09 '11 at 21:06
  • @Gene: Sure. So will `foo = assert(blurf)`. Again, why not make it robust in all cases if it's so easy to do. – Kerrek SB Aug 09 '11 at 21:08
  • @Kerrek - I really don't see anything specifically good (or bad) about this choice in C standard, the reasons for one or the other are weak anyway. – Gene Bushuyev Aug 09 '11 at 21:13
  • 4
    Don't forget that `assert()` is required to expand "to a void expression" by the standard. I'm sure the requirement is in the standard for reasons that align with many of the comments here. But as far as a particular implementation is concerned, that's all the rationale that's necessary. – Michael Burr Aug 09 '11 at 21:19
  • @Gene: one specific reason to avoid having a macro that should act like an expression be simply 'empty' is that there are times where an empty expression is not permitted. One example (and one is all it takes to be enough to say it shouldn't be done) is as one of the components to a conditional expression. Note that even though GCC allows empty components to the conditional operator, it's an extension that can't be counted on in general. – Michael Burr Aug 09 '11 at 21:32