TL:DR; #define 定义符号,#ifdef 测试符号是否定义而不是它是否有值。
#define WIN32_BUILD
这定义了一个预处理器令牌,WIN32_BUILD。令牌没有价值。在您使用令牌“WIN32_BUILD”的任何地方,预处理器都会替换空字符串,即什么都没有。
#ifdef WIN32_BUILD
这会检查是否定义了预处理器令牌 WIN32_BUILD。是的,你刚刚定义了它。
#ifdef WIN32_BUILD
// true - this code is included.
#define PCH "stdafx.h"
这定义了预处理器令牌 PCH,并为其分配值“stdafx.h”
#else
#define PCH "xyz.h"
#endif
此代码被忽略,因为 WIN32_BUILD 已定义。
您似乎希望“ifdef”仅在表达式未定义 /to/ 时才计算为真。
#define a
#define b SOMETHING
#ifdef a
// you are expecting this to be ignored
#endif
#ifdef b
// and expecting this not to be ignored
#endif
#ifdef 和 #if defined(...) 做同样的事情。
#define a
#define b SOMETHING
#if defined(a) && defined(b)
// this code will be evaluated, both tokens are defined.
#endif
预处理器标记的这一特性通常用于支持条件功能:
#if HAVE_CPP11_OVERRIDE_KEYWORD
#define OVERRIDE_FN override
#else
#define OVERRIDE_FN
#endif
struct A {
virtual void foo() {}
};
struct B : public A {
void foo() OVERRIDE_FN {}
};
在上面的代码中,override关键字只有在系统支持的情况下才会被添加(在代码之外确定)。
所以带有override 的编译器会看到
struct B : public A {
void foo() override {}
};
没有它的编译器会看到
struct B : public A {
void foo() {}
};
注意:“ifdef”的反义词是“ifndef”:
#define a
#define b SOMETHING
#undef c
//#define d // << we didn't define it.
int main() {
#ifdef a
#pramga message("a is defined")
#else
#pramga message("a is UNdefined")
#endif
#ifdef b
#pragma message("b is defined")
#else
#pramga message("b is UNdefined")
#endif
#ifdef c
#pramga message("c is defined")
#endif
#else
#pramga message("c is UNdefined")
#endif
#ifdef d
#pramga message("d is defined")
#endif
#else
#pramga message("d is UNdefined")
#endif
#ifndef d
#pragma message("d is not defined")
#endif
#ifndef a
#pragma message("a is not defined")
#endif
return 0;
}
您可以分配一个预处理器令牌数值并使用#if 对其进行测试
#if _MSC_VER
#define WIN32_BUILD 1
#else
#define WIN32_BUILD 0
#endif
#if WIN32_BUILD
#include <Windows.h>
#endif
但是,特别是在进行跨平台编程时,人们倾向于使用ifdef 变体而不是数字检查,因为值检查要求您明确确保所有标记都用值定义。仅在需要时定义它们要容易得多。