assert macro
Some implementations tolerate an arbitrary scalar expression as the
argument to assert,
but the Committee decided to require correct operation only for
int expressions.
For the sake of implementors,
no hard and fast format for the output of a failing assertion is required;
but the Standard mandates enough machinery to replicate
the form shown in the footnote.
It can be difficult or impossible to make assert a true function,
so it is restricted to macro form only.
To minimize the number of different methods for program termination,
assert is now defined in terms of the
abort function.
Note that defining the macro NDEBUG to disable assertions may
change the behavior of a program with no failing assertion
if any argument expression to assert has side-effects,
because the expression is no longer evaluated.
It is possible to turn assertions off and on in different
functions within a translation unit by defining (or undefining)
NDEBUG and including <assert.h> again.
The implementation of this behavior in <assert.h> is simple:
undefine any previous definition of assert before providing
the new one.
Thus the header might look like
#undef assert
#ifdef NDEBUG
#define assert(ignore) ((void) 0)
#else
extern void __gripe(char *_Expr, char *_File, int _Line);
#define assert(expr) \
( (expr)? (void)0 : __gripe(#expr, __FILE__, __LINE__) )
#endif
Note that assert must expand to a void expression,
so the more obvious if statement does not suffice as a definition
of assert.
Note also the avoidance of names in a header which would conflict
with the user's name space (see §3.1.2.1).