Next: , Previous: , Up: Macro Pitfalls   [Contents][Index]


26.5.10.4 Duplication of Side Effects

Many C programs define a macro min, for “minimum”, like this:

#define min(X, Y)  ((X) < (Y) ? (X) : (Y))

When you use this macro with an argument containing a side effect, as shown here,

next = min (x + y, foo (z));

it expands as follows:

next = ((x + y) < (foo (z)) ? (x + y) : (foo (z)));

where x + y has been substituted for X and foo (z) for Y.

The function foo is used only once in the statement as it appears in the program, but the expression foo (z) has been substituted twice into the macro expansion. As a result, foo might be called twice when the statement is executed. If it has side effects or if it takes a long time to compute, that may be undesirable. We say that min is an unsafe macro.

The best solution to this problem is to define min in a way that computes the value of foo (z) only once. In general, that requires using __auto_type (see Referring to a Type with __auto_type). How to use it for this is described in the following section. See Using __auto_type for Local Variables.

Otherwise, you will need to be careful when using the macro min. For example, you can calculate the value of foo (z), save it in a variable, and use that variable in min:

#define min(X, Y)  ((X) < (Y) ? (X) : (Y))
/*  */
{
  int tem = foo (z);
  next = min (x + y, tem);
}

(where we assume that foo returns type int).

When the repeated value appears as the condition of the ?: operator and again as its iftrue expression, you can avoid repeated execution by omitting the iftrue expression, like this:

#define x_or_y(X, Y)  ((X) ? : (Y))

In GNU C, this expands to use the first macro argument’s value if that isn’t zero. If that’s zero, it compiles the second argument and uses that value. See Conditional Expression.


Next: Using __auto_type for Local Variables, Previous: Swallowing the Semicolon, Up: Macro Pitfalls   [Contents][Index]