Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do people use #ifdef for feature flag tests?

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.

like image 914
Ben Voigt Avatar asked Jan 22 '14 01:01

Ben Voigt


Video Answer


1 Answers

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.

like image 163
Adam Avatar answered Sep 26 '22 14:09

Adam