为什么人们使用#ifdef进行功能标记测试?

Ben*_*igt 14 c c++ conditional-compilation c-preprocessor

人们建议大范围#ifdef进行条件编译.一个搜索#ifdef证实,它的使用是很普遍的.

然而#ifdef NAME(或等同#if defined(NAME)和相关#ifndef NAME(和#if !defined(NAME))有一个严重的缺陷:

header.h

#ifndef IS_SPECIAL
#error You're not special enough
#endif
Run Code Online (Sandbox Code Playgroud)

source.cpp

#include "header.h"
Run Code Online (Sandbox Code Playgroud)

gcc -DIS_SPECIAL source.cpp

显然,将会通过

source1.cpp

#define IS_SPECIAL 1
#include "header.h"
Run Code Online (Sandbox Code Playgroud)

但是,也一样

source0.cpp

#define IS_SPECIAL 0
#include "header.h"
Run Code Online (Sandbox Code Playgroud)

这是完全错误的事情.而一些C++编译器,传递一个以C模式处理的文件(由于扩展或命令行选项)有效#define __cplusplus 0.我看到事情破裂了

#ifdef __cplusplus
extern "C" {
#endif
/* ... */
#ifdef __cplusplus
}
#endif
Run Code Online (Sandbox Code Playgroud)

C模式下处理,其中extern "C"语法无效,因为__cplusplus实际上是自动定义的0.

另一方面,这适用于所有编译器:

#if __cplusplus
extern "C" {
#endif
/* ... */
#if __cplusplus
}
#endif
Run Code Online (Sandbox Code Playgroud)

为什么人们仍然#ifdef在这种情况下使用?他们根本没有意识到#if在未定义的名字上工作得很好吗?或者条件编译#ifvs 有实际的缺点#ifdef吗?


显然,#ifdef确实有有效用途,例如为可配置参数提供默认值:

#ifndef MAX_FILES
#define MAX_FILES 64
#endif
Run Code Online (Sandbox Code Playgroud)

我只讨论旗帜测试的情况.

Ada*_*dam 3

为什么人们在这种情况下仍然使用#ifdef?

个人意见:从命令行控制稍微容易一些。我-DOPTION更喜欢-DOPTION=1.

而且,名称的存在显然是二元的。我不必能够处理{0,非零,未定义}。

他们是否只是不知道#if 对于未定义的名称可以完美地工作?

我不知道。这有什么语义?未定义的名称是否假定为 0?我是否需要向一个几乎不了解预处理器的人解释这一点?

或者 #if 与 #ifdef 对于条件编译有实际的缺点吗?

对我来说,名称存在的二元性#ifdef/#ifndef是一个清晰的好处。另外,我对任一构造的主要用途是用于包含防护。那个图案是最干净的#ifndef

  • `-DOPTION` 和 `-DOPTION=1` 之间没有区别(对于我曾经使用过的任何预处理器)。两者都定义了一个值为“1”的宏“OPTION”。 (4认同)