3

This is the definition of the assert macro in Visual Studio 2019

#ifdef NDEBUG

    #define assert(expression) ((void)0)

#else

    _ACRTIMP void __cdecl _wassert(
        _In_z_ wchar_t const* _Message,
        _In_z_ wchar_t const* _File,
        _In_   unsigned       _Line
        );

    #define assert(expression) (void)(                                                       \
            (!!(expression)) ||                                                              \
            (_wassert(_CRT_WIDE(#expression), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0) \
        )

#endif

As you can see above, the definition of the macro assert in a release build is

#define assert(expression) ((void)0)

Why can't it be just #define assert(expression) 0 ?

Belloc
  • 6,318
  • 3
  • 22
  • 52
  • Related: [Why is assert is defined as (void)0?](https://stackoverflow.com/questions/36329271/why-is-assert-is-defined-as-void0). (Not a duplicate as it focuses on another alternative, but it might be of interest to people finding this question in the future.) – JaMiT May 09 '20 at 19:18
  • @JaMiT I was not convinced by the answers given in the linked question. So I decided to ask the same question in [Visual C++](https://social.msdn.microsoft.com/Forums/vstudio/en-US/fc439bc5-8547-41fa-9d26-cb9e5dff6ed0/why-does-the-assert-macro-has-to-expand-to-void0-in-a-release-build?forum=vcgeneral). And I got a brilliant answer by Igor Tandetnik there. – Belloc May 09 '20 at 19:46
  • * shrug * Igor does give a nice example there. However, you might note that somewhere on this page (to the right in wide browsers, towards the bottom in narrow) there is now a "Linked" section with a link to *"Why is assert defined as (void)0?"*. I can add a related SO question to that section by adding a comment. Adding a related non-SO question is not so simple. ;) – JaMiT May 09 '20 at 20:05

2 Answers2

3

This prevents using assert as an expression. So if one does (by mistake):

a = assert(something);

The compiler will throw an error both for a release and debug build.

Julien Thierry
  • 651
  • 4
  • 11
  • It took me a while to accept what you said. But your answer is the correct one. Great answer by the way! – Belloc May 11 '20 at 13:25
  • @Belloc There isn't necessarily a single "correct" answer; there can be multiple reasons. Also, this answer is slightly inaccurate. The `(void)` cast prevents `assert()` from being an *rvalue*, but it still could be used as an *expression*. For example: `condition ? assert(something) : assert(somethingElse)` or `assert(condition), puts("hello")`. – jamesdlin May 14 '20 at 12:20
  • @jamesdlin You'll find the reason I accepted Julien's answer instead of yours [here](http://coliru.stacked-crooked.com/a/0a98afe72577f244). Basically, Julien's answer appears to better explain this example, as there is no warning in this case. I also noticed the small inaccuracy in Julien's answer. But that was a very small issue in my judgement, to not decide in his favor. – Belloc May 15 '20 at 12:49
2

Some compilers might want the (void) cast to suppress warnings about an expression whose value isn't used.

jamesdlin
  • 81,374
  • 13
  • 159
  • 204