Macro Substitution
A definition has the form:
#define name replacement text
It calls for a macro substitution of the simplest kind - subsequent occurrences of the token name will be replaced by the replacement text. The name in a #define
has the same form as a variable name; the replacement text is arbitrary. Normally the replacement text is the rest of the line, but a long definition may be continued onto several lines by placing a \
at the end of each line to be continued. The scope of a name defined with #define
is from its point of definition to the end of the source file being compiled. A definition may use previous definitions. Substitutions are made only for tokens, and do not take place within quoted strings. For example, if YES
is a defined name, there would be no substitution in printf("YES")
or in YESMAN
.
Any name may be defined with any replacement text. For example:
#define forever for (;;) /* infinite loop */
defines a new word, forever
, for an infinite loop.
It is also possible to define macros with arguments, so the replacement text can be different for different calls of the macro. As an example, define a macro called max
:
#define max(A, B) ((A) > (B) ? (A) : (B))
Although it looks like a function call, a use of max
expands into in-line code. Each occurrence of a formal parameter (here A or B) will be replaced by the corresponding actual argument. Thus the line:
x = max(p+q, r+s);
will be replaced by the line:
x = ((p+q) > (r+s) ? (p+q) : (r+s));
So long as the arguments are treated consistently, this macro will serve for any data type; there is no need for different kinds of max for different data types, as there would be with functions.
If you examine the expansion of max
, you will notice some pitfalls. The expressions are evaluated twice; this is bad if they involve side effects like increment operators or input and output. For instance:
max(i++, j++) /* WRONG */
will increment the larger twice. Some care also has to be taken with parentheses to make sure the order of evaluation is preserved; consider what happens when the macro:
#define square(x) x * x /* WRONG */
is invoked as square(z+1)
.
Nonetheless, macros are valuable. One practical example comes from <stdio.h>
, in which getchar
and putchar
are often defined as macros to avoid the run-time overhead of a function call per character processed. The functions in <ctype.h>
are also usually implemented as macros.
Names may be undefined with #undef
, usually to ensure that a routine is really a function, not a macro:
#undef getchar
int getchar(void) { ... }
Formal parameters are not replaced within quoted strings. If, however, a parameter name is preceded by a #
in the replacement text, the combination will be expanded into a quoted string with the parameter replaced by the actual argument. This can be combined with string concatenation to make, for example, a debugging print macro:
#define dprint(expr) printf(#expr " = %g\n", expr)
When this is invoked, as in:
dprint(x/y)
the macro is expanded into:
printf("x/y" " = %g\n", x/y);
and the strings are concatenated, so the effect is
printf("x/y = %g\n", x/y);
Within the actual argument, each "
is replaced by \"
and each \
by \\
, so the result is a legal string constant.
The preprocessor operator ##
provides a way to concatenate actual arguments during macro expansion. If a parameter in the replacement text is adjacent to a ##
, the parameter is replaced by the actual argument, the ##
and surrounding white space are removed, and the result is re-scanned. For example, the macro paste
concatenates its two arguments:
#define paste(front, back) front ## back
so :
paste(name, 1)
creates the token name1
.
The rules for nested uses of ##
are arcane; further details may be found in Appendix A.
Exercise 4-14. Define a macro swap(t,x,y)
that interchanges two arguments of type t
. (Block structure will help.)