#ifdef DEBUG versus #if DEBUG

It is unclear to me when using compiler directives which of the below two code snippets is correct/preferred and why. It seems that most developers and Open Source projects I've seen use the first but I have seen the second used frequently as well.

#ifdef DEBUG
[self doSomethingOnlyWhenDebugging];
#endif

VERSUS

#if DEBUG
[self doSomethingOnlyWhenDebugging];
#endif

Which of the above code snippets is preferable for running code only while debugging and why? My guess is that the first will run if DEBUG is defined as TRUE or FALSE where the second will run only if DEBUG is defined and set to TRUE. Is that correct?


You are correct. #if DEBUG will not evaluate if DEBUG is defined as 0.

As for when to use each, you can stick to using #ifdef for anything where you only need to add code if the preprocessor definition is present, such as adding debug logging. If you need to inspect the value and go down different compilation paths, then I would use a 0 or 1. A good example of that is TARGET_IPHONE_SIMULATOR, which is always defined for an iOS project, but only 1 if you’re compiling for the simulator.


As I know, the finest choice is:

#ifndef DEBUG
    NSLog(@"-1");
#elif DEBUG == 0
    NSLog(@"0");
#else
    NSLog(@"%d", DEBUG);
#endif

then, you will know #ifndef DEBUG is preferred above all others.

There is a simpler choice:

#if DEBUG == 0 // DEBUG is not defined or defined to be 0
    // do sth
#else
    // do sth
#endif

However, if -Wundef compiler flag is on, there might be a warning with #if DEBUG == 0.


You need to look at the code where DEBUG gets defined or not defined, and write your code accordingly. With DEBUG, you will find that it is either not defined, or defined with a value of 1. So either #if DEBUG or #ifdef DEBUG will work.

For #define's that are under your control, I recommend that you always define them, either with a value of 0 or 1. You can then use #if to check for the value, but you can also use them directly in an ordinary if statement or in an expression, which may make your code more readable. And since it is always defined, you can use "Jump To Definition" in Xcode to go to the place where it is defined and check how and why it is set. If instead you either #define or not #define the value, and it is not defined, then Xcode will have no idea where in your source code it is not defined. It also gives you a chance to look for misspelled uses. If "Jump to Definition" doesn't work, then you know you have spelled it wrong.

BTW Within an #if directive, any macro that is not defined is replaced by 0. So #if DEBUG will work if DEBUG is not defined, or if DEBUG is defined as 0, and it will not compile if DEBUG is defined as nothing - which will tell you what is wrong so you can fix it. From that point of view, using #if is better unless it doesn't compile.