The #define directive specifies a macro identifier and a replacement list, and terminates with a new-line character. The replacement list, a sequence of preprocessing tokens, is substituted for every subsequent occurrence of that macro identifier in the program text, unless the identifier occurs inside a character constant, a comment, or a literal string. The #undef directive is used to cancel a definition for a macro.
A macro definition is independent of block structure, and is in effect from the #define directive that defines it until either a corresponding #undef directive or the end of the compilation unit is encountered.
The #define directive has the following syntax:
#define identifier replacement-list newline
#define identifier ( identifier-list(opt) )
If the replacement-list is empty, subsequent occurrences of the identifier are deleted from the source file.
The first form of the #define directive is called an object-like macro. The second form is called a function-like macro.
The #undef directive has the following syntax:
#undef identifier newline
This directive cancels a previous definition of the identifier by #define . Redefining a macro previously defined is not legal, unless the new definition is precisely the same as the old.
The replacement list in the macro definition, as well as arguments in a function-like macro reference, can contain other macro references. DEC C does not limit the depth to which such references can be nested.
For a given macro definition, any macro names contained in the replacement list are themselves replaced by their currently specified replacement lists. If a macro name being defined is contained in its own replacement list or in a nested replacement list, it is not replaced. These nonreplaced macro names are then no longer available for further replacement, even if they are later examined in contexts in which they would otherwise be replaced.
The following example shows nested #define directives:
/* Show multiple substitutions and listing format. */
#define AUTHOR james + LAST
#define LAST michener
writer = AUTHOR;
#define LAST joyce
writer = AUTHOR;
After this example is compiled with the appropriate options to show intermediate macro expansions, the following listing results:
1 /* Show multiple substitutions and listing format. */
3 #define AUTHOR james + LAST
7 int writer, james, michener, joyce;
9 #define LAST michener
10 writer = AUTHOR;
10.1 james + LAST
11 #undef LAST
12 #define LAST joyce
13 writer = AUTHOR;
13.1 james + LAST
On the first pass, the compiler replaces the identifier AUTHOR with the replacement list james + LAST . On the second pass, the compiler replaces the identifier LAST with its currently defined replacement list value. At line 9, the replacement list value for LAST is the identifier michener , so michener is substituted at line 10. At line 12, the replacement list value for LAST is redefined to be the identifier joyce , so joyce is substituted at line 13.
The #define directive may be continued onto subsequent lines if necessary. To do this, end each line to be continued with a backslash (\) immediately followed by a new-line character. The backslash and new-line characters do not become part of the definition. The first character in the next line is logically adjacent to the character that immediately precedes the backslash. The backslash/newline as a continuation sequence is valid anywhere. However, comments within the definition line can be continued without the backslash/newline.
If you plan to port programs to and from other C implementations, take care in choosing which macro definitions to use within your programs, because some implementations define different macros than others.