Previous Table of Contents Next


3.8.2. Macro Definition (#define)

A line of the form

#define name replacement-text

defines a preprocessor macro with the given name and a value consisting of the replacement-text (if any). Macro names follow the same rules as other identifiers (see section 3.2.4), although it is customary to give them capitalized names because it is often important to know that a given identifier represents a preprocessor macro as opposed to an ordinary variable or function.

The replacement text can be almost anything. Often it is a simple constant, but it can also be a more complicated expression, or in fact any arbitrary string of tokens, whether syntactically valid in isolation or not. The preprocessor merely replaces all later occurrences of the macro name (except inside comments and string literals) with the replacement text, and the results are passed on to the compiler proper for interpretation.

For example, we might write

#define MAXLINE 100
char line[MAXLINE];
char *p = fgets(line, MAXLINE, stdin);

This code defines a manifest constant MAXLINE with the “value” (or replacement text) 100. The macro is used in two places, as the dimension of the line array and as the second argument to the fgets function (see section 3.10.1.2). Besides making the code somewhat more self documenting, use of the macro ensures that if its value is changed—that is, to accommodate longer lines—all instances of it will be changed automatically by the preprocessor during subsequent compilations. Furthermore, because preprocessor macro replacement is performed before formal compilation, the macro MAXLINE is perfectly appropriate as an array dimension, although an ordinary (i.e., runtime) variable would not be. In other words, the code seen by the compiler after the macro is expanded is simply

char line[100];
char *p = fgets(line, 100, stdin);

Notice that a line containing a #define directive is neither a declaration nor a statement and therefore need not be terminated by a semicolon. Any semicolon in a #define line is simply treated as part of the replacement text, and would be copied blindly into the source stream at the point of invocation, which can lead to unexpected syntax errors.

A second form of preprocessor macro is also available. A line of the form

#define name( parameters ) replacement-text

defines a “function-like macro” that accepts zero or more arguments. Where the parameter names appear in the replacement text, they are replaced with the actual arguments supplied during “invocation” of the macro. For example, we might write

#define Square(x) x * x

to define a simple macro for squaring a number. (As we will see, it is a bit too simple.) An invocation such as

a = Square(b);

would be expanded by the preprocessor to

a = b * b;

If the argument text for a function-like macro involves more macro names, those macros are expanded first, before substituting for the function-like macro parameters.

Preprocessor macros, especially of the function-like variety, must be defined and used with care. When you’re defining a function-like macro, there must be no space between the macro name and the open parenthesis indicating the presence of an argument list. (Otherwise, the parenthesis would be assumed to be part of the replacement text of an ordinary, non-function-like macro.) More importantly, the simple, textual substitution of preprocessor macro replacement text (of both the ordinary and function-like variety) can lead to surprising results. To see why, consider these examples:

a = Square(b + 1);
c = 1. / Square(d);

These would be expanded to

a = b + 1 * b + 1;
c = 1. / d * d;

which, due to the precedence and associativity of addition, multiplication, and division, would not be evaluated as the programmer presumably intended them to be. Defining the macro instead as

#define Square(x) ((x) * (x))

guards against both of these problems. For safety’s sake, a macro that expands to an expression should always have that expression parenthesized in the definition. Furthermore, in a function-like macro, all instances of the parameters should be parenthesized if the replacement text is an expression.

One further pitfall deserves note. An invocation like

a = Square(b++);

expands to

a = ((b++) * (b++));

which is undefined, due to multiple side effects involving the same variable b. There is no good fix for this problem; function-like macros are simply not perfect substitutes for true functions. (In particular, the parentheses do not resolve the evaluation order ambiguity; see also section 3.3.9. Some compilers support “inline” functions, as in C++, and this extension is likely to be made official in the next revision of the C standard.)

Besides preprocessor macros defined by a particular source file, several macros are predefined. The ANSI/ISO C Standard specifies __STDC__ (which is always defined in a standard-conforming compiler), __FILE__ and __LINE__, which expand to the current source filename and line number, and __DATE__ and __TIME__, which expand to strings representing the date and time of compilation. Besides these macros, particular compilers may predefine their own macros, having to do with the compiler, operating system, or other aspects of the environment. (Such macros are primarily useful for directing conditional compilation; see the next section.)


Previous Table of Contents Next