The #define
Directive
You can use the
#define directive to give a meaningful name to a constant in your
program. The two forms of the syntax are:
Syntax
#define
identifier token-stringopt
#define
identifier[( identifieropt,
... , identifieropt )] token-stringopt
The #define
directive substitutes token-string for all subsequent occurrences of
an identifier in the source file. The identifier is replaced
only when it forms a token. For instance, identifier is not replaced
if it appears in a comment, within a string, or as part of a longer
identifier.
A #define
without a token-string removes occurrences of identifier from
the source file. The identifier remains defined and can be tested
using the #if defined and #ifdef directives.
The token-string argument consists of a series of tokens, such as keywords,
constants, or complete statements. One or more white-space characters must
separate token-string from identifier. This white space is not
considered part of the substituted text, nor is any white space following
the last token of the text.
Formal
parameter names appear in token-string to mark the places where
actual values are substituted. Each parameter name can appear more than once
in token-string, and the names can appear in any order. The number of
arguments in the call must match the number of parameters in the macro
definition. Liberal use of parentheses ensures that complicated actual
arguments are interpreted correctly.
The second
syntax form allows the creation of function-like macros. This form accepts
an optional list of parameters that must appear in parentheses. References
to the identifier after the original definition replace each
occurrence of identifier( identifieropt, ..., identifieropt ) with a version of the
token-string
argument that has actual arguments substituted for formal parameters.
The formal
parameters in the list are separated by commas. Each name in the list must
be unique, and the list must be enclosed in parentheses. No spaces can
separate identifier and the opening parenthesis. Use line
concatenation — place a backslash (\) before the newline character —
for long directives on multiple source lines. The scope of a formal
parameter name extends to the new line that ends token-string.
When a macro
has been defined in the second syntax form, subsequent textual instances
followed by an argument list constitute a macro call. The actual arguments
following an instance of identifier in the source file are matched to
the corresponding formal parameters in the macro definition. Each formal
parameter in token-string that is not preceded by a stringizing (#),
charizing (#@), or token-pasting (##) operator, or not
followed by a ## operator, is replaced by the corresponding actual
argument. Any macros in the actual argument are expanded before the
directive replaces the formal parameter. (The operators are described in
Preprocessor Operators.)
The following
examples of macros with arguments illustrate the second form of the #define syntax:
// Macro to define cursor lines
#define CURSOR(top, bottom) ((top) << 8) | bottom))
// Macro to get a random integer with a specified range
#define getrandom(min, max) \
((rand()%(int)(((max) + 1)-(min)))+ (min))
Arguments with
side effects sometimes cause macros to produce unexpected results. A given
formal parameter may appear more than once in token-string. If that
formal parameter is replaced by an expression with side effects, the
expression, with its side effects, may be evaluated more than once. (See the
examples under Token-Pasting Operator (##).)
The #undef
directive causes an identifier’s preprocessor definition to be forgotten.
See The #undef Directive for more information.
If the name of
the macro being defined occurs in token-string (even as a result of
another macro expansion), it is not expanded.
A second #define for a macro with the same name generates an error unless the
second token sequence is identical to the first.
Microsoft
Specific
Microsoft C/C++
allows the redefinition of a macro, but generates a warning, provided the
new definition is lexically identical to a previous definition. ANSI C
considers macro redefinition an error. For example, these macros are
equivalent for C/C++ but generate warnings:
#define test( f1, f2 ) ( f1 * f2 )
#define test( a1, a2 ) ( a1 * a2 )
END
Microsoft Specific
This example
illustrates the #define directive:
#define WIDTH 80
#define LENGTH ( WIDTH + 10 )
The
first statement defines the identifier
WIDTH
as the integer constant 80 and defines LENGTH in terms of
WIDTH and the integer
constant 10. Each occurrence of LENGTH
is replaced by (WIDTH + 10).
In turn, each occurrence of WIDTH + 10
is replaced by the expression (80 + 10).
The parentheses around WIDTH + 10
are important because they control the interpretation in statements such as
the following:
var = LENGTH * 20;
After the
preprocessing stage the statement becomes:
var = ( 80 + 10 ) * 20;
which evaluates
to 1800. Without parentheses, the result is:
var = 80 + 10 * 20;
which evaluates
to 280.
Microsoft
Specific
Defining macros
and constants with the /D compiler option has the same effect as using a #define preprocessing directive at the beginning of your file. Up to 30
macros can be defined with the /D option. |