smking@lion.waterloo.edu (Scott M. King) (01/16/90)
In article <721@eedsp.eedsp.gatech.edu> baud@eedsp.UUCP (Kurt Baudendistel) writes:
:Be careful, however, of the nasty C preprocessor, which will make this
:nice looking and appealing definition:
: #define SWAP(a,b) {typeof (a) tmp; tmp=a; a=b; b=tmp}
:fail in many cases, like
: if (x < y)
: SWAP (x, y); // bracketing of SWAP makes the `;' extraneous
: else // and fatal
: x = y;
:
:Kurt Baudendistel --- GRA
:Georgia Tech, School of Electrical Engineering, Atlanta, GA 30332
:internet: baud@eedsp.gatech.edu uucp: gatech!gt-eedsp!baud
To make a macro behave exactly as a statement, replace the { and } in
the macro definition with START_MACRO and END_MACRO:
#define START_MACRO do {
#define END_MACRO } while ( 0 )
The compiler should catch uses with too few or too many semi-colons here.
(Note that another version I have seen has very unexpected effects if the
semi-colon is left off the macro usage:
#define START_MACRO if ( 1 ) {
#define END_MACRO } else
)
Scott M. King, Software Devlopment Group, University of Waterloo
david@sun.com (``Bob'' is the gun and YOU are the bullet...) (01/17/90)
In article <19840@watdragon.waterloo.edu> smking@lion.waterloo.edu (Scott M. King) writes: >To make a macro behave exactly as a statement, replace the { and } in >the macro definition with START_MACRO and END_MACRO: >#define START_MACRO do { >#define END_MACRO } while ( 0 ) Unfortunately this is not lint-compatible ("constant in conditional context"). I use a slight variation: #ifdef lint int _ZERO_; #else #define _ZERO_ 0 #endif #define _STMT(s) do { s } while (_ZERO_) #define FOO(bar) _STMT(if (bar) frob();) -- David DiGiacomo, Sun Microsystems, Mt. View, CA sun!david david@eng.sun.com
steveh@emtek.UUCP (Steve Hollasch) (01/21/90)
> To make a macro behave exactly as a statement, replace the { and } in > the macro definition with START_MACRO and END_MACRO: > #define START_MACRO do { > #define END_MACRO } while ( 0 ) > > The compiler should catch uses with too few or too many semi-colons here. > > (Note that another version I have seen has very unexpected effects if the > semi-colon is left off the macro usage: > #define START_MACRO if ( 1 ) { > #define END_MACRO } else I use two basic forms for multi-statement macro definitions, and ALWAYS terminate a macro invocation with a semi-colon (I think of macro invocations as inline functions, so this makes sense). An alternative method is the following: #define MACRO(a,b,c) \ ( (a)[0] = (b)[0] + (c)[0], \ (a)[1] = (b)[1] + (c)[1], \ (a)[2] = (b)[2] + (c)[2] \ ) That is, define the macro as a throwaway expression. This method seems 'cleaner' to me, since there are no implied tests. The trailing-else (or single-loop) method, however, is superior in that it allows any kind of code within the macro body. NOTE: This includes variable declarations (as in swap routines)! _______________________________________________________________________________ Steve Hollasch [uunet!emtek!steveh] Tempe, Arizona