[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