Erm... do { } while ( 0 ) does
not loop!
The assert() implementation recommended by P.J. Plauger (author of the Dinkumware library and member of the C committee) is indeed the trinary operator though.
What follows is a ripaway from how I implemented assert() in the PDCLib, provided as Public Domain.
assert.h:
Code:
#ifndef _KERNEL_ASSERT
#define _KERNEL_ASSERT
#if __STDC_VERSION__ == 199901L
void _Kassert_99( char const * const, char const * const, char const * const );
#else
void _Kassert( char const * const );
#endif
#define __symbol2value( x ) #x
#define __symbol2string( x ) __symbol2value( x )
#endif
/* re-including assert.h results in assert() being redefined */
#undef assert
#ifdef NDEBUG
#define assert( ignore ) ( (void) 0 )
#else
#if __STDC_VERSION__ == 199901L
#define assert( expression ) ( ( expression ) ? (void) 0 \
: _Kassert( "Assertion failed: " #expression \
", function ", __func__, \
", file " __FILE__ \
", line " __symbol2string( __LINE__ ) \
"." ) )
#else
#define assert( expression ) ( ( expression ) ? (void) 0 \
: _Kassert( "Assertion failed: " #expression \
", file " __FILE__ \
", line " __symbol2string( __LINE__ ) \
"." ) )
#endif
#endif
Implement _Kassert() and _Kassert_99() to do whatever you like. The char* contain e.g.:
"Assertion failed: x == 0, file mykernel.c, line 385." for _Kassert(), and
"Assertion failed: x == 0, function "
"mykernel_map_table"
", file mykernel.c, line 285." for _Kassert_99(), respectively.
Only C99 does have __func__ specified, hence the __STDC_VERSION__ check. Above implementation allows you to use this assert() in exactly the way described by the C standard (i.e., you may include assert.h multiple times, the macro is defined to nothing when NDEBUG is set etc.)
Hope this helps.