Side Effect of Macros

Using macros can be desirable for its practical uses. Since compilers basically replace the code written in macros, they are easily tend to error and debugging can be hard. Misuses are mostly happening during the use of function-like macros (especially parameterized macros). Comparison of signed and unsigned variable inputs is another risk. Even if you write your macros so carefully, it doesn’t eliminate some unintended results.

Let’s check some examples to see the erroneous usages:

Unsafe Usage #1

#define _ABS(x) (((x) < 0) ? -(x) : (x))
int b;
void func(int a) {
  b = _ABS(++a);
 }

In this usage, n is desired to be incremented after given input argument to the _ABS function. But what actually happening here is:

b = (((++a) < 0) ? -(++a) : (++a));

Here the value of a is incremented twice rather than once. You can see even if the simplest function-like macro can result in error.

Unsafe Usage #2

#define _MIN(X, Y)  ((X) < (Y) ? (X) : (Y))
  
void func(int n) {
  min = _MIN(a + b, bar(c));
}

Here what the preprocessor is going to do is:

min = ( (a + b) < ( bar(c) ) ? (a + b) : ( bar(c) ) );

This usage calls the function called bar twice. This may cause undesirable results in the function and it takes longer time. To avoid this situation, call the bar function and then use the returned value in macro.

WHAT TO USE?

There are still so many different examples for unsafe macros. Don’t let your code be vulnerable and don’t write unsafe. Prefer inline functions instead of function-like macros.

Leave a Reply

Your email address will not be published. Required fields are marked *