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:
#ifndef IS_SPECIAL
#error You're not special enough
#endif
#include "header.h"
gcc -DIS_SPECIAL source.cpp
will pass, obviously, as will
#define IS_SPECIAL 1
#include "header.h"
But, so will
#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.
Why do people still use #ifdef in this scenario?
Personal opinion: it's marginally easier to control from the command line. I prefer -DOPTION
over -DOPTION=1
.
Also, existence of a name is clearly binary. I don't have to be able to handle {0, non-zero, undefined}.
Are they simply unaware that #if works perfectly fine on undefined names?
I wasn't aware. What are the semantics of this? Is an undefined name assumed to be 0? Do I want to have to explain that to the guy who barely understands the preprocessor to begin with?
Or is there an actual disadvantage to #if vs #ifdef for conditional compilation?
To me, the binary nature of #ifdef/#ifndef
of name existence is a clarity benefit.
Also, my primary usage of either construct is for include guards. That pattern is cleanest with #ifndef
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With