Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site hcrvx1.UUCP Path: utzoo!hcrvax!hcrvx1!hugh From: hugh@hcrvx1.UUCP (Hugh Redelmeier) Newsgroups: net.sources.bugs,net.lang.c Subject: Re: C-Debug package, possible problems depending on program structure Message-ID: <1089@hcrvx1.UUCP> Date: Mon, 21-Jan-85 16:11:30 EST Article-I.D.: hcrvx1.1089 Posted: Mon Jan 21 16:11:30 1985 Date-Received: Tue, 22-Jan-85 00:43:54 EST References: <1885@wateng.UUCP> Organization: Human Computing Resources, Toronto Lines: 54 In article <1885@wateng.UUCP> ksbszabo@wateng.UUCP (Kevin Szabo) writes: >You may note that all of Fred's macros ... >have the form: > >#define DBUG_2( keyword, format ) \ > if(_db_on) {_dp_printf_( __LINE__, keyword, format );} > >In the very rare case of the following usage, the `else' clause will >incorrectly bind to the `if(_db_on)' provided in the macro. > > if( some_thing_worth_noting_happens ) > DBUG_2( "interesting", "info" ); > else > do the normal thing; > >... The fix is to enclose the macro's in another >set of {}. > >#define DBUG_2( keyword, format ) \ > {if(_db_on) {_dp_printf_( __LINE__, keyword, format );};} > Whenever I define a macro to be an expression, I put parens around it to avoid surprises. Similarly, whenever I define a macro to be a (compound) statement, I put braces around it. There are two places where braces cause problems: IF statements with ELSE clauses and DO statements: void proc() { ... } #define mac() { ... } if (...) mac(); else ...; <---- wrong! if (...) mac() else ...; <---- right if (...) proc(); else ...; <---- right if (...) proc() else ...; <---- wrong! if (...) { proc_or_mac(); } while (...); <---- best? The same examples apply to DO. In fact, it applies even if the macro definition ends in semicolon, without the braces: #define mac() ...; I think this shows how the following three features of C don't combine perfectly: - semicolons as terminators (as opposed to separators) - semicolons DON'T terminate blocks - statement composition is not done with bracketing constructs (except for {}) PS: How often have you forgotten to put the semicolon after an initializer contained in braces? int primes[] = {2, 3, 5, 7, }; PPS: But thank goodness we can use the commas in an initializer as terminators (e.g. last comma above).