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__) ) #endifNote 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).