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.
The assert keyword lets you test if a condition in your code returns True, if not, the program will raise an AssertionError.
The assert() function tests the condition parameter. If it is false, it prints a message to standard error, using the string parameter to describe the failed condition. It then sets the variable _assert_exit to one and executes the exit statement. The exit statement jumps to the END rule.
In the C Programming Language, assert is a macro that is designed to be used like a function. It checks the value of an expression that we expect to be true under normal circumstances. If expression is a nonzero value, the assert macro does nothing.
An assert is a preprocessor macro that is used to evaluate a conditional expression. If the conditional expression evaluates false, then the program is terminated after displaying the error message.
The C++ standard defers the definition of assert
to the C standard.
” 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 theabort
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.
” 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 ofNDEBUG
.
A reasonable definition of the double-whammy discussed above can likewise depend on NDEBUG
with no include guard, e.g.
#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
.
It will always fail. That's pretty much it. It will fail always for the same reason that "assert(x == 5)" will succeed whenever x = 5.
If you're asking for an application then you would put it in code blocks that really shouldn't happen.
switch(suit) {
case CLUB:
case DIAMOND:
case HEART:
case SPADE:
// ...
default:
assert(0);
}
Yes, it will always fail.
assert(0)
or assert(false)
is usually used to mark unreachable code, so that in debug mode a diagnostic message is emitted and the program is aborted when the supposedly unreachable is actually reached, which is a clear signal that the program isn't doing what we think it is.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With