【问题标题】:Conditional preprocessing puzzle条件预处理难题
【发布时间】:2014-04-09 01:22:02
【问题描述】:

我有一个问题,我似乎无法让条件 #define 预处理器正常工作。例如:

#define WIN32_BUILD
#ifdef WIN32_BUILD
  #define PCH "stdafx.h"
#else
  #define PCH "xyz.h"
#endif

#include PCH

如果我使用这种形式,编译器会告诉我它找不到“stdafx.h”。好吧,这似乎很奇怪,所以如果我将代码更改为....

#define WIN32_BUILD
#ifdef WIN32_BUILD
  #define PCH "xyz.h"
#else
  #define PCH "stdafx.h"
#endif

#include PCH

然后在 PCH 中定义的文件被拾取,一切编译正常。这对我来说似乎很奇怪,几乎就像预处理器忽略了 #if 指令并只使用它遇到的所有 #defines。

显然我做错了什么,我希望有人能帮助我理解这一点。

【问题讨论】:

  • 我想你想要#else,而不是#elif。你没有第二个条件,它只是一个正常的“其他”。
  • @RaphaelMiedl:不确定这是否是问题的原因,更多的是我在查看代码时注意到的。但是,如果它似乎解决了 OP 的问题,我还是会添加作为答案。
  • #else 也会发生同样的事情。
  • 然后我将删除我的答案 - 评论已达到目的,答案不再相关。

标签: c++ visual-c++ visual-studio-2012


【解决方案1】:

当一个项目开启了预编译头功能时,预处理器会忽略 #include "stdafx.h" 之前的所有内容

因此您的#define 语句将被忽略。

【讨论】:

  • 哦,这看起来很奇怪。我该怎么办?
  • 在预编译头的项目设置中,您可以关闭该功能,或者您可以将预编译头文件的名称更改为 xyz.h 并删除您在#之前的所有定义/ifdef行包括
【解决方案2】:

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 变体而不是数字检查,因为值检查要求您明确确保所有标记都用值定义。仅在需要时定义它们要容易得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-26
    • 1970-01-01
    • 2019-04-29
    相关资源
    最近更新 更多