Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site lsuc.UUCP Path: utzoo!lsuc!msb From: msb@lsuc.UUCP (Mark Brader) Newsgroups: net.lang.c Subject: Re: context-independent macros Message-ID: <350@lsuc.UUCP> Date: Mon, 4-Feb-85 01:32:34 EST Article-I.D.: lsuc.350 Posted: Mon Feb 4 01:32:34 1985 Date-Received: Mon, 4-Feb-85 01:39:56 EST References: <1885@wateng.UUCP> <1089@hcrvx1.UUCP> <33@daisy.UUCP> <1097@hcrvx1.UUCP> <695@ucbtopaz.CC.Berkeley.ARPA> <11839@gatech.UUCP> Reply-To: msb@lsuc.UUCP (Mark Brader) Organization: Law Society of Upper Canada, Toronto Lines: 75 Summary: Expressions are not the same as statements (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@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@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.