What does assert(0) mean?

Smith Western picture Smith Western · Dec 12, 2015 · Viewed 23.7k times · Source

I had a question like this on one of my exams and I'm still not too sure how to answer it. I understand that assertions are ways to test your program, however I'm not too sure what assert(0) is checking. Is this a trick question? It will always fail, but I don't understand why. What is it checking?

Any explanation would be great, thanks.

Answer

Cheers and hth. - Alf picture Cheers and hth. - Alf · Dec 12, 2015

The C++ standard defers the definition of assert to the C standard.

C99 §7.2/2:

The assert macro puts diagnostic tests into programs; it expands to a void expression. When it is executed, if expression (which shall have a scalar type) is false (that is, compares equal to 0), the assert macro writes information about the particular call that failed (including the text of the argument, the name of the source file, the source line number, and the name of the enclosing function — the latter are respectively the values of the preprocessing macros __FILE__ and __LINE__ and of the identifier __func__) on the standard error file in an implementation-defined format. It then calls the abort function.


In assert(0) the 0 is interpreted as false, so this assertion will always fail, or fire, when assertion checking is on.

Thus it asserts that

“The execution will never reach this point.”

In practice it can be difficult to make compilers shut up about the execution reaching or not reaching a given point. Often the compiler will first complain about the execution possibly reaching the end of a function without returning a value. Adding an assert(0) there should ideally solve that issue, but then the compiler may complain about the assert, or not recognize that it says you're already well aware of what it tries to warn about.

One (1)possible measure then is to also throw an exception at that point:

auto foo( int x )
    -> int
{
    if( x == 1 ) { return 42; }
    assert( 0 ); throw 0;       // Should never get here!
}

Of course that double-whammy can be defined as a higher level macro. Regarding the exception type you may want to keep it as not a std::exception, because this is not an exception intended to be caught by an ordinary catch anywhere. Or, if you trust the standard exception hierarchy (it doesn't make sense to me, but) you can use a std::logic_error.


To turn off assert assertion checking you can define the symbol NDEBUG before including <assert.h>.

This header has special support so that you can include it multiple times, with or without NDEBUG defined.

C++11 §17.6.2.2/2:

A translation unit may include library headers in any order (Clause 2). Each may be included more than once, with no effect different from being included exactly once, except that the effect of including either <cassert> or <assert.h> depends each time on the lexically current definition of NDEBUG.

A reasonable definition of the double-whammy discussed above can likewise depend on NDEBUG with no include guard, e.g.

File assert_should_never_get_here.hpp
#include <stdexcept>        // std::logic_error
#include <assert.h>

#undef ASSERT_SHOULD_NEVER_GET_HERE
#ifdef NDEBUG
#   define ASSERT_SHOULD_NEVER_GET_HERE() \
        throw std::logic_error( "Reached a supposed unreachable point" )
#else
#   define ASSERT_SHOULD_NEVER_GET_HERE() \
        do{ \
            assert( "Reached a supposed unreachable point" && 0 ); \
            throw 0; \
        } while( 0 )
#endif

Disclaimer: While I coded that up a number of times in the early 2000s, I cooked up the code above just for this answer, and while I did test it with g++ it may not necessarily be perfect.


(1) See Basile Starynkevitch's answer for discussion of another possibility, the g++-specific intrinsic __builtin_unreachable.