Just as you can have conditionals within your C code that may or may not execute code depending on whether a condition is true or false, you can write C preprocessor conditionals. These are directives that instruct the preprocessor to do something (or not do something) based on certain criteria. Unlike your C conditionals, which are checked during execution of an application, C preprocessor conditionals are tested during the preprocessor stage (just before compilation).
There are a number of conditional directives in the C preprocessor (Table 8.1), allowing for relatively intricate examples.
Conditional Directives | |
---|---|
Directive | Effect |
#if | Includes code up to the next #else or #endif if the expression is true |
#else | Includes code up to the next #endif if the preceding #if expression is false |
#elif | Includes code up to the next #else or #endif if the included expression is true; can only follow an #if expression |
#endif | Used to indicate the end of a conditional directive |
#ifdef | Includes code up to the next #else or #endif if the referenced definition exists |
#ifndef | Includes code up to the next #else or #endif if the referenced definition does not exist |
One particularly common use of conditional directives is to ensure that a macro is only defined once, no matter how many times an application actually attempts to include the header file that defines it. Our next example demonstrates this concept.
1. | |
2. | Before the first #define directive add this conditional (Script 8.7 on the next page): #ifndef MY_MATH_H Script 8.7. C preprocessor directives can be made more complex by creating conditionals.This begins a C preprocessor conditional whose condition is the equivalent of saying If the MY_MATH_H macro has not been defined… You'll see why and how this conditional works after the next step. |
3. | Add a macro defining MY_MATH_H. #define MY_MATH_H You don't even need to assign a value to the macro, as long as it is defined. In essence, the MY_MATH_H macro is a marker used for indicating whether the my_math header file and its subsequent macro definitions have been included or not. If the file has been included, then MY_MATH_H and the other macros have been defined and do not need to be defined again. If the file has not been included, then all of the macros will be defined here. |
4. | At the end of the file, close the conditional: #endif This terminates the conditional begun in Step 2. Thus, all of the macro definitions are within the conditional. |
5. | Save the file as my_math2.h. |
6. | Open include.c in your text editor or IDE (Script 8.6). This program will be modified to use this new header file. |
7. | Change the #include directive so that it includes the my_math2.h file (Script 8.8): #include "./my_math2.h" Script 8.8. This program makes use of the new my_math2 file, which only defines macros if they have not yet been defined. |
8. | Make sure that a copy of my_math.h is in the same directory as condition.c (this file). |
9. | Save the file as condition.c, compile, and debug. |
10. | Run the executable (Figure 8.14). Figure 8.14. A C preprocessor condition has been added to the code ensuring that the header file is included only once. This has no effect on the end result but does add a level of protection. |
✓ Tip
Conditional directives are most often used to compile code differently depending on the target architecture. This allows you to have a single code base but still allow for OS-dependent optimizations, changes, and so on.