Previous | Table of Contents | Next |
Several related preprocessor directives support the conditional inclusion or exclusion of source code. The first form to look at is
#ifdef name source code #endif
If a preprocessor macro of the given name is defined, the source code between the #ifdef line and the corresponding #endif is passed on to the rest of the compiler, as usual. If no macro by that name is defined, the enclosed code is discarded. The replacement text of the macro (if defined) is immaterial; the macro is simply being used as a switch, with a decision being made depending on whether or not the macro is defined at all. The conditionally included code might have to do with debugging, optional functionality, or a particular compilation environment or target operating system.
A closely related directive is #ifndef, which enables the enclosed code only if a certain macro is not defined. For more generality, the #if directive is available:
#if expression source code #endif
The expression is a restricted form of compile-time constant expression, using only long int arithmetic. If the expressions value is nonzero, the enclosed code is enabled. One special operator is supported: defined(name) evaluates to 1 if a macro by the given name is defined; 0 otherwise. Therefore, #ifdef name is equivalent to #if defined(name), and #ifndef name is equivalent to #if !defined(name).
An #else directive may be used with #ifdef, #ifndef, and #if:
#ifdef name source code #else alternate source code #endif
Depending on whether the macro is defined, one set of source code or the other will be enabled. There is also an #elif directive, which can be used to simplify a cascaded chain of #if/#else/#if directives.
Within the replacement text of preprocessor macros, two special operators are available. The # operator stringizes a macro parameter, resulting in a string literal containing the source code text of the parameter. For example, given the macro
#define Str(x) #x
the invocation Str(abc) expands to abc (that is, including the quotes). In practice, abc is often itself a macro, and the goal is to obtain its replacement text as a string literal, in which case the following auxiliary macro can be used, which works by forcing an additional macro evaluation and substitution:
#define Xstr(x) Str(x)
Now, assuming the prior definition
#define abc def
the invocation Xstr(abc) expands to def. As a more realistic example, the stringizing operator can be used (along with string literal concatenation) to construct strings containing variable names, such as in this debugging macro:
#define DEBUGi(x) printf(#x is %d\n, x)
Given this definition, the call DEBUGi(a) expands to
printf(a is %d\n, a)
or, after string literal concatenation,
printf(a is %d\n, a)
and prints the value of a.
The second operator is ##, the token-pasting operator, which splices identifiers or other tokens together. For example, given the definition
#define Paste(a, b) a ## b
the code
Paste(ab, cd) = 123
expands to the assignment abcd = 123. (Without the ## operator, the expansion would have been ab cd = 123, which would have been a syntax error.)
The #line directive resets the preprocessors and compilers notion of the current source file and/or line number, for the purposes of error messages and the like. The syntax is either
#line lineno
or
#line lineno filename
This directive is useful when C source is being automatically generated from some other source, and error messages should be correlated with that other source.
The #error directive prints a user-specified error message during compilation. The syntax is
#error message
where message is any text. A programmer might use #error to report a mismatched or unimplemented set of conditional compilation options.
Finally, the #pragma directive permits any sort of compiler-specific extensions to be specified.
Every C program begins execution with an implicit call to the function main(). One function named main must be defined by the programmer, using one of two signatures: either
int main(void)
or
int main(int argc, char **argv)
These forms are not absolute; several stylistic variations are possible. The explicit return type int in either form, and the keyword void in the first form, can both be omitted, because int is the default return type and because an empty pair of parentheses in a function definition indicates zero arguments (see section 3.5.1). Any names may be chosen for the parameters, but argc and argv are traditional.
Previous | Table of Contents | Next |