section 4.11.2: Macro Substitution

#defines last for the whole file; you can't have local ones like you can for local variables.

``Substitutions are made only for tokens'' means that a substitutable macro name is only recognized when it stands alone. Also, substitution never happens in quoted strings, because it turns out that you usually don't want it to. Strings are generally used for communication with the user, while you want substitutions to happen where you're talking to the compiler.

The point of the ``forever'' example is to demonstrate that the replacement text doesn't have to be a simple number or string constant. You'd use the forever macro like this:

	forever {
		...
	}
which the preprocessor would expand to
	for (;;) {
		...
	}
which, as we learned in section 3.5 on page 60, is an infinite loop. (Presumably there's a break; see section 3.7 p. 64.)

Another popular trick is

	#define ever ;;
so that you can say
	for(ever) {
		...
	}
But ``preprocessor tricks'' like these tend to get out of hand very quickly; if you use too many of them you're not writing in C any more but rather in your own peculiar dialect, and no one will be able to read your code without understanding all of your ``silly little macros.'' It is best if simple macros expand to simple constants (or expressions).

Macros with arguments are also called ``function-like macros'' because they act almost like miniature functions. There are some important differences, however:

page 90

The correct way to write the square() macro is

	#define square(x) ((x) * (x))
There are three rules to remember when defining function-like macros:

  1. The macro expansion must always be parenthesized so that any low-precedence operators it contains will still be evaluated first. If we didn't write the square() macro carefully, the invocation
    	1 / square(n)
    
    might expand to
    	1 / n * n
    
    while it should expand to
    	1 / (n * n)
    
  2. Within the macro definition, all occurrences of the parameters must be parenthesized so that any low-precedence operators the actual arguments contain will be evaluated first. If we didn't write the square() macro carefully, the invocation
    	square(n + 1)
    
    might expand to
    	n + 1 * n + 1
    
    while it should expand to
    	(n + 1) * (n + 1)
    
  3. If a parameter appears several times in the expansion, the macro may not work properly if the actual argument is an expression with side effects. No matter how we parenthesize the square() macro, the invocation
    	square(i++)
    
    would result in
    	i++ * i++
    
    (perhaps with some parentheses), but this expression is undefined, because we don't know when the two increments will happen with respect to each other or the multiplication.
Since the square() macro can't be written perfectly safely, (arguments with side effects will always be troublesome), its callers will always have to be careful (i.e. not to call it with arguments with side effects). One convention is to capitalize the names of macros which can't be treated exactly as if they were functions:
	#define Square(x) ((x) * (x))

page 90 continued

#undef can be used when you want to give a macro restricted scope, if you can remember to undefine it when you want it to go out of scope. Don't worry about ``[ensuring] that a routine is really a function, not a macro'' or the getchar example.

Also, don't worry about the # and ## operators. These are new ANSI features which aren't needed except in relatively special circumstances.


Read sequentially: prev next up top

This page by Steve Summit // Copyright 1995, 1996 // mail feedback