人recommend #ifdef
for conditional compilation by a wide margin。 search for #ifdef
证实其使用是普遍的。
然而#ifdef NAME
(或等效#if defined(NAME)
及相关#ifndef NAME
(和#if !defined(NAME)
)存在严重缺陷:
#ifndef IS_SPECIAL
#error You're not special enough
#endif
#include "header.h"
显然,gcc -DIS_SPECIAL source.cpp
会通过
#define IS_SPECIAL 1
#include "header.h"
但是,
也是如此#define IS_SPECIAL 0
#include "header.h"
这是完全错误的事情。一些C ++编译器传递了以 C 模式处理的文件(由于扩展或命令行选项),有效地执行#define __cplusplus 0
。
#ifdef __cplusplus
extern "C" {
#endif
/* ... */
#ifdef __cplusplus
}
#endif
在 C 模式下处理,extern "C"
语法无效,因为__cplusplus
实际上已自动定义为0
。
另一方面,这对所有编译器都是正确的:
#if __cplusplus
extern "C" {
#endif
/* ... */
#if __cplusplus
}
#endif
为什么人们在这种情况下仍然使用#ifdef
?他们根本不知道#if
对未定义的名字完全正常吗?或条件编译#if
与#ifdef
是否存在实际不利之处?
显然,#ifdef
确实具有有效用途,例如为可配置参数提供默认值:
#ifndef MAX_FILES
#define MAX_FILES 64
#endif
我只讨论旗帜测试的情况。
答案 0 :(得分:3)
为什么人们在这种情况下仍然使用#ifdef?
个人意见:从命令行控制起来稍微容易一些。我更喜欢-DOPTION
而不是-DOPTION=1
。
此外,名称的存在显然是二进制的。我不必处理{0,非零,未定义}。
他们根本没有意识到#if在未定义的名称上运行得很好吗?
我不知道。这有什么语义?假定未定义的名称是0吗?我是否想要向那些几乎不了解预处理器的人解释一下?
对于条件编译,#if vs #ifdef是否存在实际缺点?
对我来说,名称存在的#ifdef/#ifndef
的二元性质是明确的好处。
另外,我对这两种构造的主要用法是包含警戒。使用#ifndef
时,该模式最为清晰。
答案 1 :(得分:2)
我不能说为什么一般人更喜欢#ifdef
而不是#if
,但我至少可以说我为什么这样做。基于刚才的内省(自从你问过 - 我以前从未明确考虑过它),有两个原因:
1)我更喜欢我的宏(我试图谨慎使用)尽可能地使用最直接的语义,并相应地作为"类型免费"尽可能。我假设宏,如果它们有任何类型,则是"类型自由函数" (注意:这里我更喜欢模板,但有时候一切......)或者基本上只是 boolean 标志。因此,即使为宏指定值1
,也会为我拉伸它。 (例如,如果你有#define _cplusplus 2
,它应该是什么意思?它应该以什么方式与1
不同?)
2)关于他们的最后一点是" flags"我主要将这些用于我在命令行(或IDE)中指定的内容作为条件编译标志。实际上,在我的软件团队中,当我们编写C ++时,我们基本上已经禁止了#34;从使用宏到其他任何东西。即使在条件编译的情况下,如果我们可以通过其他方式解决问题(例如通过模块化),我们也会尽量避免使用它们。
这两个原因都与相同的基本假设有关,即尽可能避免使用宏(在C ++中),因此不需要类型的复杂性或不透明的语义。如果你没有做出这个假设(并且在用C语言编程时它不常见,我知道),那么这会改变一些事情,我想你对#if
的观点可能会有更多的影响。 / p>