Not a big fan of #ifdef or #ifndef

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
#else
#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("FOO!");
#else
printf("NOT FOO!");
#endif

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.