The C Programming Language, Ansi C
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:
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
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:
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:
When this is invoked, as in
dprint(x/y)