PATH
Conditionals are useful in macros or assertions, because those are the only ways that an expression's value can vary from one compilation to another. An #if command whose expression uses no macros or assertions is equivalent to #if 1 or #if 0; you might as well determine which one--by computing the value of the expression yourself--and then simplify the program.
For example, here's a conditional that tests the expression BUFSIZE == 1020 , where BUFSIZE must be a macro:
#if BUFSIZE == 1020
printf ("Large buffers!\n");
#endif /* BUFSIZE is large */
(Programmers often wish they could test the size of a variable or data type in #if expressions, but this does not work. The preprocessor does not understand sizeof , or typedef names, or even the type keywords such as int .)
The special operator defined is used in #if expressions to test whether a certain name is defined as a macro. Either defined NAME or defined (NAME) is an expression whose value is 1 if NAME is defined as macro at the current point in the program, and 0 otherwise. For the defined operator it makes no difference what the definition of the macro is; all that matters is whether there's a definition. Thus, for example,
#if defined (vax) || defined (ns16000)
will include the following code if either vax or ns16000 is defined as a macro.
If a macro is defined and later undefined with #undef , subsequent use of the defined operator returns 0, because the name is no longer defined. If the macro is defined again with another #define , defined will again return 1.
Conditionals that test just the definedness of one name are very common, so there are two special short conditional commands for this case:
Macro definitions can vary between compilations for any of the following reasons:
The #error command causes the preprocessor to report a fatal error. The rest of the line that follows #error is used as the error message.
You would use #error inside a conditional that detects a combination of parameters that you know the program doesn't support.
For example, if you know that the program won't run properly on a VAX, you might write
#ifdef vax
#error Won't work on Vaxen. See comments at get_last_object.
#endif
Similarly, if you have several configuration parameters that must be set up by the installation in a consistent way, you can use conditionals to detect an inconsistency and report it with #error . For example:
#if (HASH_TABLE_SIZE % 2 == 0) || (HASH_TABLE_SIZE % 3 == 0) \
|| (HASH_TABLE_SIZE % 5 == 0)
#error HASH_TABLE_SIZE shouldn't be divisible by a small prime
#endif
The #warning command is like the #error command, but causes the preprocessor to issue a warning and continue preprocessing. The rest of the line that follows #warning is used as the warning message.
You might use #warning in obsolete header files, with a message directing the user to the header file which should be used instead.