context-independent macros

Mark Brader msb at lsuc.UUCP
Mon Feb 4 16:32:34 AEST 1985


(main article ~35 lines ... quotes at end, with remarks interspersed)

There have been a number of items lately about the apparently simple macro

	#define	assert(x)	if (!(x)) complain ("x not true");

As has been said, if you write it this way, then you can't say something
like
	if (z) assert (z == 1); else z = a;

Various fixes have been discussed, with dummy ifs, dummy dos, braces,
and omitted semicolons.  Each method either has its own similar problems,
or is ugly, or is subject to dangerous semicolon typos.
The key is that what we really want is for

	assert(x);

to behave syntactically just as if it was really a function call.  Well,
suppose it was.  Then this would be a valid statement because an *expression*
followed by a semicolon is a statement.  But a compound statement with
braces, or an if-statement, or a do-statement, is *not* an expression.
This is the root of the difficulties.

So the solution is to write the macro to only use an expression:

	#define	assert(x)	((x)? 0: complain ("x not true"))
or
	#define	assert(x)	((x) || complain ("x not true"))

I think everybody will find the first form clearer except sh programmers. :-)

Of course, this solution fails when the macro really has to contain
a genuine loop or its own local variables, but I claim that most of
the time an if is all you want.  And in that case, writing the macro
to expand to an expression is possible and safe.

Mark Brader




arnold at gatech.UUCP (Arnold Robbins) reposts:

> #define assert(x)  do { if (!(x)) die_miserably("x bombed\n"); } while (0)

> which will get executed exactly once, and protects the macro syntactically.
> ...
> The other way is this:

> #define assert(x)	if(x) ; else die_miserably ("x bombed\n")

All I can say is that I find both of these uglier than mine.

> This topic has gone around (several times) before.

Sorry to add to it, but I haven't seen before what I'm saying this time.



mwm at ucbtopaz.UUCP (Praiser of Bob) writes:

> 	#define	macro(args)\
> 		(Statement1 ,\
> 		Statement2 ,\
> 		...
> 		Statement3)
> 
> This should work correctly anywhere a function call works, as it is a
> single statement. The question is whether or not the evaluation order is
> preserved.

This is correct if the word "statement" is replaced by "expression"
throughout.  In that case it becomes a companion to my suggestion above,
for use when you want sequential instead of conditional operations.
Order of evaluation is indeed guaranteed.



More information about the Comp.lang.c mailing list