Conditional Compilation: #if, #ifdef, #ifndef

You can use the preprocessing directives #if, #ifdef and #ifndef to control which parts of a source file get passed to the compiler. This can be useful if, for example, you want to write code that can be compiled using different compilers or on different operating systems. It is also useful if you want to build different versions of the same basic program with different feature sets.

Basically the use of #if looks like this:

#if FOO
/* Code compiled if FOO is not zero */
#elif BAR
/* Code compiled if FOO is zero but BAR is not zero */
#else
/* Code compiled if both FOO and BAR are zero */
#endif

"elif" stands for "else if". There can be any number of #elif directives (including none) before the end of the #if ... #endif sequence. The #else directive is also optional. It should be obvious from the above that macro and symbolic constant substitution is performed on the text after the #if (and other) directives before they are evaluated. But you don't need to use symbolic constants:

#if 0
/* This code is never compiled */
#endif

That type of construct can be useful during debugging.

The preprocessor also understands the keyword 'defined' which gets set to 1 if a given constant has been defined earlier (using #define), even if the actual value of the constant is zero or nothing at all. Also, you can use '!', the C logical-not operator to invert the truth-value of an expression (i.e. false, or zero expressions become true, and true, or non-zero, expressions become false), including a 'defined' expression. For example:

#if defined(FOO)
/* Code compiled if FOO is defined (even if zero) */
#endif

#if !defined(BAR)
/* Code compiled only if BAR has not been defined */
#endif

The #ifdef directive is equivalent to #if defined, and the #ifndef directive is equivalent to #if ! defined.