C++ 中 #ifdef Defined() 的奇怪行为

Aak*_*pta 0 c++ macros conditional-compilation defined

我正在 Visual Studio Community 中使用 C++20 编写跨平台代码,但我陷入了以下代码的输出:


#define WINDOWS (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
#define UNIX (defined(__unix__) || defined(__unix))

constexpr bool is_unix1()
{
#ifdef UNIX
    return true;
#else
    return false;
#endif
}

constexpr bool is_unix2()
{
#ifdef defined(UNIX)
    return true;
#else
    return false;
#endif
}


int main()
{
    cout << std::boolalpha << is_unix1() << " " << is_unix2() << endl;
}
Run Code Online (Sandbox Code Playgroud)

当我在 Windows 中从 VS Community 内部运行此代码时,我得到以下输出:

true false
Run Code Online (Sandbox Code Playgroud)

有人可以解释为什么is_unix1()评估为falsewhileis_unix2()评估为吗true

我开始知道这defined(...)是特定于编译器的,并且它不是标准 C++ 的一部分。但直接使用宏会导致奇怪的行为,我不知道在这里使用哪种方法。

use*_*522 7

defined不是特定于编译器的。它是在 C++ 标准中指定的。

#ifdef defined(UNIX)根本就不是有效的语法,编译器必须对此进行诊断。#ifdef后面必须跟一个标识符,然后是换行符。它根据标识符是否定义为宏来有条件地编译代码。

#ifdef UNIX因此总是编译 then 分支,因为您UNIX事先定义为宏。

你想要的似乎是这样的

#if (defined(__unix__) || defined(__unix))
Run Code Online (Sandbox Code Playgroud)

#if根据给定表达式进行条件编译,该表达式可以包含defined运算符,这些运算符单独计算结果01取决于标识符是否定义为宏。

但是,您不能隐藏在宏(defined(__unix__) || defined(__unix))后面UNIX,然后让它在控制#if表达式中展开。如果这样的扩展产生令牌defined,则程序的行为是未定义的。

所以你真正想要的而不是你的定义UNIX

#if (defined(__unix__) || defined(__unix))
#define UNIX
#endif
Run Code Online (Sandbox Code Playgroud)

然后后来

#ifdef UNIX
Run Code Online (Sandbox Code Playgroud)