#define directive — Defines a macro
#defineidentifier
definition
#defineidentifier
( )definition
#defineidentifier
( )definition
#defineidentifier
(identifier-list
)definition
The #define
directive defines
a macro named identifier
. The macro's
replacement text is the list of tokens shown as
definition
. The macro can be simple, with
no arguments, or can have an argument list. The argument list is
introduced by a left parenthesis that immediately follows the macro
name. If there is a space between
identifier
and (
, the (
is interpreted as the start of the definition of a simple macro. The
identifier-list
can be empty, or it can be
a list of identifiers separated by commas. Whitespace is permitted in
the identifier-list
and before the closing
parenthesis.
C programmers are accustomed to using macros to declare
constants and simple inline functions, but C++ offers const
declarations, true inline functions,
and templates. Macros are therefore used much less often in C++ than
in C. The main drawback to macros is that they do not obey scope or namespace
rules. When you must use macros, a common convention is to use all
uppercase letters for the macro names, and never use all uppercase
letters for non-macro names.
A macro's scope is from the point of definition to the end
of the source file, or until you undefine the macro with the #undef
directive. If you try to repeat a macro definition, the
new definition must be identical to the original definition. The only
way to give a macro a different definition is to undefine it
first.
If you #include
any
standard header, a macro name cannot be the same as a reserved
keyword or any of the names declared in the header. Many compilers
accept keywords as macro names, but your program would still be
wrong and would not be portable to a compiler that is more strict
about detecting this particular error. Even if you do not #include
a standard header, using
macros to redefine keywords is usually a bad
idea.
Wherever a macro name appears as a distinct token after its definition, it is replaced with the replacement text. Macro names are not replaced inside string and character literals, however. The replacement text is rescanned for macro names, which are recursively expanded until no more replacements take place. During replacement, the original macro name is not expanded if it appears in any replacement text. Here is a simple example of a macro definition and use:
#define NAME "NAME = Tempest Software, Inc." char companyName[] = NAME;
During the macro expansion phase of compilation, the token NAME
will be replaced by its expansion, with
the following result:
char companyName[] = "NAME = Tempest Software, Inc.";
The replacement text is never interpreted as a preprocessing
directive. This means, for example, you cannot #define
a macro within a macro's replacement
text. Also, directive names are not subject to macro replacement
(although directive arguments are).
You can also declare a macro with a parameter list, which is sometimes called a function-like macro :
#define DECLARE(x,y, z) x y = z #define PRINT(a) (::std::cout << (a) << '\n')
To use a function-like macro, the macro name must be followed by a comma-separated argument list in parentheses. A single argument can contain balanced parentheses, and within those parentheses, you can have commas, which are not interpreted as argument separators. The macro invocation must have the same number of arguments as the macro definition has parameters. Newlines are permitted as ordinary whitespace characters in a macro invocation.
The following example uses the DECLARE
and PRINT
macros defined in the previous
example:
int main( ) { DECLARE(int, x, 42); PRINT((x = 10, x+2)); }
In the macro replacement text, each occurrence of a parameter name is replaced by the corresponding argument. For example, the macro expansion for the previous example results in the following:
int main( ) { int x = 42; (::std::cout << (x = 10, x + 2) << '\n'); }
You must be extra cautious when using a template instantiation
as a macro argument. The angle brackets that surround the template
arguments are not treated specially for macro arguments, so commas
that separate the template arguments are interpreted as separators for
the macro arguments. In the following example, the DECL
macro attempts to declare an object
named n
with type t
. This works fine for a simple type, such
as int
, but fails with a template
instantiation. When used with map<int,int>
, the comma separates
macro arguments, so the preprocessor sees three macro
arguments—std::map<int
, int>
, and m
—and reports an error:
#define DECL(t, n) t n = t( ) DECL(int, zero); // Expands to int zero = int( ) DECL(std::map<int,int>, m); // Error
When a macro is expanded, the macro arguments are expanded, and
each parameter is replaced by its corresponding expanded argument
unless the parameter is an operand to the #
or ##
operator. After the arguments have been expanded, the #
and ##
operators are evaluated, and the resulting text is rescanned for
macros. The macro name is expanded only once, so rescanning does not
expand the name of the macro being expanded.
The following macros are predefined. Do not undefine or redefine any of the predefined macros.
_ _cplusplus
Has the value 199711L
.
Future versions of the C++ standard will use a larger value.
Nonconforming compilers should use a different value.
_ _DATE_
_
Expands to the date of compilation, as a string literal,
in the form "Mmm dd
yyyy
", in which dd
begins with a space for numbers
less than 10. An implementation is free to substitute a
different date, but the form is always the same, and the date is
always valid.
_ _FILE_ _
Expands to the name, as a string literal, of the source file being compiled.
_ _LINE_ _
Expands to the line number, as a decimal constant, of the source file being compiled.
_ _STDC_
_
Is implementation-defined. C++ compilers might define this
macro; if it is defined, the value is implementation-defined.
Note that C compilers are required to define _ _STDC_ _
as 1
, and in some implementations, the
same preprocessor might be used for C and C++.
_ _TIME_
_
Expands to the compilation time, as a string literal, in
the form "hh:mm:ss
". An
implementation is free to substitute a different time, but the
form is always the same, and the time is always valid.
An implementation is free to predefine other macros that use any
of the reserved names, such as names that contain two adjacent
underscores or a leading underscore followed by an uppercase letter.
For example, compilers often define macros to indicate the host or
target platform—e.g., _ _linux_ _
.
Consult your compiler's documentation for details.
When writing a container class template (see Chapter 10), it is important to detect
when a template parameter is an integral type. There are several ways
to do this. One way is to use type traits (Chapter 8). A template declares a
special tag for all integral types and a different tag for all other
types. The traits template is then specialized for the integral types,
which is repetitive, tedious, and error-prone. Using a macro, however,
reduces the opportunity for errors because the macro body is written
once. Example 11-1 shows
how the DECL_IS_INTEGER
macro specializes the is_integer
class template for each built-in
integral type.
Example 11-1. Defining type traits with a macro
// Type trait to test whether a type is an integer. struct is_integer_tag {}; struct is_not_integer_tag {}; // The default is that a type is not an integral type. template<typename T> struct is_integer { enum { value = 0 }; typedef is_not_integer_tag tag; }; // Explicitly override the default for all integral types. #define DECL_IS_INTEGER(T) \ template<> \ struct is_integer<T> { \ enum { value = 1 }; \ typedef is_integer_tag tag; \ } DECL_IS_INTEGER(bool); DECL_IS_INTEGER(char); DECL_IS_INTEGER(signed char); DECL_IS_INTEGER(unsigned char); DECL_IS_INTEGER(int); DECL_IS_INTEGER(unsigned int); DECL_IS_INTEGER(short); DECL_IS_INTEGER(unsigned short); DECL_IS_INTEGER(long); DECL_IS_INTEGER(unsigned long); #undef DECL_IS_INTEGER
Example 11-2 shows
another way that macros are used when testing the string
class. The TEST
macro calls a function and prints the
result. The TEST
macro cannot be
implemented as a function because it uses the #
operator.
Most compilers have an option in which the compiler runs only the preprocessor, and you can examine the results after all macros have been expanded and all preprocessor directives have been evaluated. This mode can be helpful when debugging an incorrect macro expansion.
Example 11-3 is a contrived example that illustrates how macros are expanded. Try running the example through your compiler to see if the results are correct. (Other than whitespace, the results should be the same as what is shown in the rest of this section.)
Example 11-3. Expanding macros
#define x x.y #define STR(x) #x #define XSTR(s) STR(s) #define CONCAT(x, y) x ## y #define PARENS(x) (x) #define APPLY(x,y) x(y) #define hello HI x // x.y CONCAT(ST, R)(hello) // "hello" CONCAT(X,STR)(hello) // "HI" CONCAT(S, TR)PARENS(hello) // STR(HI) CONCAT(S, TR)(PARENS(hello)) // "PARENS(hello)" APPLY(CONCAT(S, TR), hello) // "HI"
The first macro expansion shows how the macro name x
is not expanded in the replacement text.
The result is simply:
x.y
The second macro expansion shows how the CONCAT
macro forms a new token STR
from its arguments. After the CONCAT
macro is evaluated, the text is
rescanned. The STR
macro is then
invoked with the hello
argument.
Because the x
parameter is an
operand of #
, the argument is not
expanded. Instead, #
is applied to
hello
to produce the result:
"hello"
The third macro expansion is like the second, except it invokes
XSTR
instead of STR
. The difference is that XSTR
expands its argument, s
, because the replacement text, STR(s)
, does not use the #
or ##
operators. Thus, XSTR(hello)
expands to STR(HI)
, which has the
following result:
"HI"
The fourth expansion also invokes CONCAT
to produce STR
, but STR
is not followed by a left parenthesis,
so it is not expanded as a macro. Instead, it is followed by the
PARENS
macro. The parameter of
PARENS
is not an operand of
#
or ##
, so it is expanded, which means the
argument hello
expands to HI
, and the final result is:
STR(HI)
The fifth expansion is just like the second, but emphasizes how
the argument to STR
is not
expanded. The result is:
"PARENS(hello)"
The final macro expansion shows how to expand hello
as an argument to STR
, even when STR
is the result of the CONCAT
macro. The parameters of APPLY
are expanded, resulting in the text
STR(HI)
, which expands to:
"HI"