Why do people use #ifdef for feature flag tests?

江枫思渺然 提交于 2019-12-05 15:31:35

问题


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.


回答1:


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.




回答2:


I cannot speak to why people in general prefer #ifdef over #if, but I can at least say why I do. Based on introspection just now (since you asked -- I've never considered it explicitly before), there are 2 reasons:

1) I prefer my macros (which I try to use sparingly) to have the most straightforward semantics as possible, and correspondingly as "type free" as possible. I assume that macros, if they have any type at all, are either "type free functions" (note: here I would strongly prefer templates, but there are times for everything...) or basically just boolean flags. Hence, even assigning a value of 1 to a macro is stretching it for me. (For example, what should it mean if you have #define _cplusplus 2? Should that be different in any way than 1?)

2) This last bit about them being "flags" goes along with the fact that I mostly use these for things I specify on the command line (or in the IDE) as conditional compilation flags. Indeed, on my software team, when we're writing C++, we're basically "prohibited" from using macros for anything else. And even in the conditional compilation case, we try to avoid them if we can solve the problem some other way (such as via modularity).

Both of these reasons relate to that same underlying assumption that macro use is to be avoided as much as possible (in C++) and so should not need the complexities of types or opaque semantics. If you don't make this assumption (and it's less common when programming in C, I know), then that changes things such that I imagine your points about #if might hold more sway.



来源:https://stackoverflow.com/questions/21272744/why-do-people-use-ifdef-for-feature-flag-tests

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!