I am not a big fan of the C/C++ preprocessor directives #ifdef or #ifndef. I am not denying that they certainly have their place and usage in the language. I'll first write about where I think they are useful and then about the situations where I feel they are not. #ifndef is very useful for preventing multiple inclusions of a header which will cause redefinition errors.

#ifndef __FOO_H__ // only proceed if the token is not yet defined
#define __FOO_H__ // define the token so that subsequent includes have it defined

[...contents of the header...]

#endif // __FOO_H__, end for #ifndef statement

Of course, you can use #pragma once to do the same thing, but that is a Microsoft specific extension to the language so not everyone will use it. This usage is error prone though. I can't count the number of times that I copied one header to create another header in the same project and forgot to change the #ifndef token to a new token and couldn't figure out why my new header wasn't being evaluated properly.

#ifdef is useful in a header to switch between ANSI and wide versions of the function, such as this example from winbase.h:

#ifdef UNICODE
#define CreateFile  CreateFileW
#define CreateFile  CreateFileA
#endif // !UNICODE

Now, the reason I don't like these 2 directives is that they behave differently then #if token or #if !token. #if token evaluates the value of token. If token is not defined, it defaults to zero and the #if token phrases evaluates to zero. On the other hand, #ifdef token evaluates to token to see if it is defined, regardless of the value of token. That means that the following code

#define FOO 0x0

#ifdef FOO
printf("NOT FOO!");
will print out "FOO!" even though FOO evaluates to zero. As I have written previously in my blog and in the newsgroups, I am big on maintainance of the code I write because the code I write will have to be maintained for years and its connection to me will eventually be lost by the developer who inherits it. What I don't like about #ifdef/ifndef in a source file (vs the header file examples above) is that at first glance, I mentally evaluate a #ifdef as a #if and more often then not, pick the wrong result when reviewing the code. Furthermore, everytime I see #ifndef I need to spend a minute or two staring at the entire statement to figure out what is going on, it is not immediately apparent to me what it is doing. Anytime I have to stare at something to figure out what it does, it is an indicator to me that others will probably do the same and it will eventually be a problem spot in the code in the future.

A lot of you may not agree with me and I am fine with that ;). Please let me know why though.