Function and Macro Arguments with Side Effects

Run-time support functions can be implemented either as functions or as macros. Avoid including expressions with side effects inside function invocations unless you are sure the function will not be implemented as a macro. Here is an illustration of how an argument with side effects can cause problems:

#define limit_number(x) ((x > 1000) ? 1000 : (x))

a = limit_number( a++ );

If a is greater than 1000, it is incremented once. If a is less than or equal to 1000, it is incremented twice, which is probably not the intended behavior.

A macro can be used safely with an argument that has side effects if it evaluates its parameter only once. You can determine whether a macro is safe only by inspecting the code.

A common example of a run-time support function that is often implemented as a macro is toupper. You will find your program's behavior confusing if you use the following code:

char c;

c = toupper( getc() );

If toupper is implemented as a function, getc will be called only once, and its return value will be translated to uppercase. However, if toupper is implemented as a macro, getc will be called once or twice, depending on whether c is upper- or lowercase. Consider the following macro example:

#define toupper(c) ( (islower(c)) ? _toupper(c) : (c) )

If you include the toupper macro in your code, the preprocessor expands it as follows:

/* What you wrote */

c = toupper( getc() );

/* Macro expansion */

ch = (islower( (getc()) ) ? _toupper( getc() ) : (getc()) );

The expansion of the macro shows that the argument to toupper will always be called twice: once to determine if the character is lowercase and the next time to perform case translation (if necessary). In the example, this double evaluation calls the getc function twice. Because getc is a function whose side effect is to read a character from the standard input device, the example requests two characters from standard input.