[Contents]   [Back]   [Prev]   [Up]   [Next]   [Forward]  

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 two times when the statement is executed. If it has side effects or if it takes a long time to compute, the results might not be what you intended. 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. The C language offers no standard way to do this, but it can be done with GNU C extensions as follows:

#define min(X, Y)                     \
({ typeof (X) __x = (X), __y = (Y);   \
   (__x < __y) ? __x : __y; })

If you do not wish to use GNU C extensions, the only solution is 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').

[Contents]   [Back]   [Prev]   [Up]   [Next]   [Forward]