[vox-tech] Nifty macro expansion bug

Mark K. Kim lugod3MAPS at cbreak.org
Thu Jan 18 20:30:27 PST 2007


On Thu, Jan 18, 2007 at 04:14:22PM -0800, Bill Kendrick wrote:
> See, myFREE() is actually a macro that looks like this:
> 
>   #define myFREE(x) if ((x) != NULL) FREE(x); x = NULL;
> 
> Two statements... hence the need for {} around the call to the macro.
> (Or, more sensibly, including {}s around what the macro expands to.)

As Gabe points out, macros should be enclosed in do{}while(0), but
defined constants with expressions should also be enclosed.  Consider
the following code:

  1: #define myConstant1     5000
  2: #define myCosntant2     myConstant1 + 2000
  3:
  4: int main() {
  5:   printf("%d\n", myConstant2 * 2);
  6: }

The expected output is 14000 ((5000+2000) * 2), but the actual output is
9000 (5000 + (2000*2)) because multiplication has higher operator
precedence than the addition.  To avoid this problem, modify the
definition of myConstant2:

  #define myCosntant2  (myConstant1 + 2000)

As a rule of thumb, make sure every #define is enclosed in something.


Another interesting case is comments on the define lines.  Consider the
case where we add C++ comments to a defined constant:

  #define myConstant2  (myConstant1 + 2000)  // my 2nd constant

expands line 5 into:

    printf("%d\n", (5000 + 2000) // my 2nd constant * 2);

in *some* compilers, which causes compiler error.  To aleviate this
problem, switch to C++-style comments:

  #define myConstant2  (myConstant1 + 2000) /* my 2nd constant */

which expands line 5 into:

    printf("%d\n", (5000 + 2000) /* my 2nd constant */ * 2);

and won't cause problems.

-Mark



More information about the vox-tech mailing list