People recommend #ifdef
for conditional compilation by a wide margin. A search for #ifdef
substantiates that its use is pervasive.
Yet #ifdef NAME
(or equivalently #if defined(NAME)
and related #ifndef NAME
(and #if !defined(NAME)
) have a severe flaw:
header.h
#ifndef IS_SPECIAL
#error You're not special enough
#endif
source.cpp
#include "header.h"
gcc -DIS_SPECIAL source.cpp
will pass, obviously, as will
source1.cpp
#define IS_SPECIAL 1
#include "header.h"
But, so will
source0.cpp
#define IS_SPECIAL 0
#include "header.h"
which is quite the wrong thing to do. And some C++ compilers, passed a file processed in C mode (due to extension or command-line option) effectively do #define __cplusplus 0
. I have seen things break when
#ifdef __cplusplus
extern "C" {
#endif
/* ... */
#ifdef __cplusplus
}
#endif
was processed in C mode, where extern "C"
is invalid syntax, because __cplusplus
was in fact automatically defined to 0
.
On the other hand, this behaves correctly for all compilers:
#if __cplusplus
extern "C" {
#endif
/* ... */
#if __cplusplus
}
#endif
Why do people still use #ifdef
in this scenario? Are they simply unaware that #if
works perfectly fine on undefined names? Or is there an actual disadvantage to #if
vs #ifdef
for conditional compilation?
Obviously, #ifdef
does have valid uses, such as providing default values for configurable parameters:
#ifndef MAX_FILES
#define MAX_FILES 64
#endif
I'm only discussing the case of flag testing.