However, once a given identifier has been replaced in a given expansion, it is not replaced if it turns up again
during rescanning; instead it is left unchanged.
Even if the final value of a macro expansion begins with with #, it is not taken to be a preprocessing directive.
The details of the macro-expansion process are described more precisely in the ANSI standard than in the first edition.
The most important change is the addition of the # and ## operators, which make quotation and concatenation admissible.
Some of the new rules, especially those involving concatenation, are bizarre. (See example below.)
For example, this facility may be used for ``manifest-constants,'' as in
#define TABSIZE 100
int table[TABSIZE];
The definition
A.12.1 Trigraph Sequences 209
The C programming Language
#define ABSDIFF(a, b) ((a)>(b) ? (a)-(b) : (b)-(a))
defines a macro to return the absolute value of the difference between its arguments. Unlike a function to do
the same thing, the arguments and returned value may have any arithmetic type or even be pointers. Also, the
arguments, which might have side effects, are evaluated twice, once for the test and once to produce the value.
Given the definition
#define tempfile(dir) #dir "%s"
the macro call tempfile(/usr/tmp) yields
"/usr/tmp" "%s"
which will subsequently be catenated into a single string. After
#define cat(x, y) x ## y
the call cat(var, 123) yields var123. However, the call cat(cat(1,2),3) is undefined: the
presence of ## prevents the arguments of the outer call from being expanded. Thus it produces the token
string
cat ( 1 , 2 )3
and )3 (the catenation of the last token of the first argument with the first token of the second) is not a legal
token. If a second level of macro definition is introduced,
#define xcat(x, y) cat(x,y)
things work more smoothly; xcat(xcat(1, 2), 3) does produce 123, because the expansion of xcat
itself does not involve the ## operator.
Likewise, ABSDIFF(ABSDIFF(a,b),c) produces the expected, fully-expanded result.
A.12.4 File Inclusion
A control line of the form
# include
causes the replacement of that line by the entire contents of the file filename. The characters in the name
filename must not include > or newline, and the effect is undefined if it contains any of ", ', \, or /*. The
named file is searched for in a sequence of implementation-defined places.
Similarly, a control line of the form
# include "filename"
searches first in association with the original source file (a deliberately implementation-dependent phrase),
and if that search fails, then as in the first form. The effect of using ', \, or /* in the filename remains
undefined, but > is permitted.
A.12.4 File Inclusion 210
The C programming Language
Finally, a directive of the form
# include token-sequence
not matching one of the previous forms is interpreted by expanding the token sequence as for normal text; one
of the two forms with or "..." must result, and is then treated as previously described.
#include files may be nested.
A.12.5 Conditional Compilation
Parts of a program may be compiled conditionally, according to the following schematic syntax.
preprocessor-conditional:
if-line text elif-parts else-partopt#endif
if-line:
# if constant-expression
# ifdef identifier
# ifndef identifier
elif-parts:
elif-line text
elif-partsopt
elif-line:
# elif constant-expression
else-part:
else-line text
else-line:
#else
Each of the directives (if-line, elif-line, else-line, and #endif) appears alone on a line. The constant
expressions in #if and subsequent #elif lines are evaluated in order until an expression with a non-zero
value is found; text following a line with a zero value is discarded. The text following the successful directive
line is treated normally. ``Text'' here refers to any material, including preprocessor lines, that is not part of the
conditional structure; it may be empty. Once a successful #if or #elif line has been found and its text
processed, succeeding #elif and #else lines, together with their text, are discarded. If all the expressions
are zero, and there is an #else, the text following the #else is treated normally. Text controlled by inactive
arms of the conditional is ignored except for checking the nesting of conditionals.
The constant expression in #if and #elif is subject to ordinary macro replacement. Moreover, any
expressions of the form
defined identifier
or
defined (identifier)
A.12.5 Conditional Compilation 211
The C programming Language
are replaced, before scanning for macros, by 1L if the identifier is defined in the preprocessor, and by 0L if
not. Any identifiers remaining after macro expansion are replaced by 0L. Finally, each integer constant is
considered to be suffixed with L, so that all arithmetic is taken to be long or unsigned long.
The resulting constant expression (Par.A.7.19) is restricted: it must be integral, and may not contain sizeof,
a cast, or an enumeration constant.
The control lines
#ifdef identifier
#ifndef identifier
are equivalent to
# if defined identifier
# if ! defined identifier
respectively.
#elif is new since the first edition, although it has been available is some preprocessors. The defined preprocessor
operator is also new.
A.12.6 Line Control
For the benefit of other preprocessors that generate C programs, a line in one of the forms
# line constant"filename"
# line constant
causes the compiler to believe, for purposes of error diagnostics, that the line number of the next source line is
given by the decimal integer constant and the current input file is named by the identifier. If the quoted
filename is absent, the remembered name does not change. Macros in the line are expanded before it is
interpreted.
A.12.7 Error Generation
A preprocessor line of the form
# error token-sequenceopt
causes the preprocessor to write a diagnostic message that includes the token sequence.
A.12.8 Pragmas
A control line of the form
# pragma token-sequenceopt
causes the preprocessor to perform an implementation-dependent action. An unrecognized pragma is ignored.
A.12.6 Line Control 212
The C programming Language
A.12.9 Null directive
A control line of the form
#
has no effect.
A.12.10 Predefined names
Several identifiers are predefined, and expand to produce special information. They, and also the preprocessor
expansion operator defined, may not be undefined or redefined.
__FILE__A string literal containing the name of the file being compiled.
__DATE__A string literal containing the date of compilation, in the form
"Mmmm dd yyyy"
__TIME__A string literal containing the time of compilation, in the form
"hh:mm:ss"
__STDC__The constant 1. It is intended that this identifier be defined to be
1 only in standard-conforming implementations.
#error and #pragma are new with the ANSI standard; the predefined preprocessor macros are new, but some of them
have been available in some implementations.
A.13 Grammar
Below is a recapitulation of the grammar that was given throughout the earlier part of this appendix. It has
exactly the same content, but is in different order.
The grammar has undefined terminal symbols integer-constant, character-constant, floating-constant,
identifier, string, and enumeration-constant; the typewriter style words and symbols are terminals given
literally. This grammar can be transformed mechanically into input acceptable for an automatic
parser-generator. Besides adding whatever syntactic marking is used to indicate alternatives in productions, it
is necessary to expand the ``one of'' constructions, and (depending on the rules of the parser-generator) to
duplicate each production with an opt symbol, once with the symbol and once without. With one further
change, namely deleting the production typedef-name: identifier and making typedef-name a terminal
symbol, this grammar is acceptable to the YACC parser-generator. It has only one conflict, generated by the [ Pobierz całość w formacie PDF ]