In the previous post I used conditional compilation to enable and disable debugging messages, yet I didn’t take the time (for those new to C/Objective-C) to explain how everything worked.
There are three ways to control compilation, the options are as follows:
1 2 3
#if constant-expression #ifdef identifier #ifndef identifier
The first example checks for a non-zero value of the constant expression. The second example looks to see if ‘identifier’ has been defined, that is, if a #define statement has been declared for the identifier. The third, #ifndef is the opposite of #ifdef
Let’s look at a few code examples:
1 2 3 4 5 6 7 8 9 10 11 12 13
#define DEBUG 1 #define MESSAGE_LEVEL 5 ... #if DEBUG something here #else something else here #endif #if MESSAGE_LEVEL > 1 printf("..."); #endif
The above example is pretty clear, if DEBUG is non-zero, include (compile) the code in the #if block, otherwise, include the code in the #else block. In the second example, a message is printed (or not) depending on the setting of MESSAGE_LEVEL.
#ifdef operates as follows:
1 2 3 4 5
#define DEBUG ... #ifdef DEBUG something here #endif
In above example, the code ‘something here’ would be compiled since DEBUG has been defined (using #define). If the line 1 above did not exist, the compiler would skip the code ‘something here’.
#ifndef is often used in C (versus Objective-C) to prevent header files from being included more than once during compilation (something that can be challenging in a large project with many source files). For example:
1 2 3 4 5 6 7
#ifndef DEBUG_HEADER #define DEBUG_HEADER // This will be seen just once by the compiler #include "header_file.h" #endif
Although this is a common approach for pure C development, using #ifndef in this manner is not a requirement in Objective-C, as the #import directive ensures that files are imported (included) just once per compilation.
Conditional compilation can be quite useful to toggle code such as debugging on/off or otherwise conditional include code. To see an example, view the post Filename and Line Number with NSLog.