将#elif 与#ifdef 一起使用是否合法?

Is it legal to use #elif with #ifdef?

一个简单的问题 Google 对我没有帮助。在 C++ 中,在 #ifdef 的上下文中使用 #elif 子句是否合法?它似乎可以在 c++11 模式(MSVC 2015/2017、clang、GCC)中与所有主要编译器一起编译和工作,但我不确定它是否符合标准。

是的,语法允许在前面加上 #elif,匹配 #if#ifdef#ifndef:

if-section:
    if-group elif-groupsopt else-groupopt endif-line

if-group:
    # if constant-expression new-line groupopt
    # ifdef identifier new-line groupopt
    # ifndef identifier new-line groupopt

请注意,#ifdef(X) 只是 #if defined(X) 的缩写,#ifndef(X)#if ! defined(X) 的缩写。

是的,这是允许的。

语法是:

if-group elif-groupsopt else-groupopt endif-line

if-group的定义不仅包括#if,还包括#ifdef#ifndef,所以#ifdef ... #elif ... #endif可以。

对我来说,这个问题最重要的一点实际上是rosshjb在问题下的评论:

@RemyLebeau Yes, we can use #ifdef with #elif. But, If we #define macro with value 0 for #ifdef case, the #ifdef case tests it to true. Otherwise, if we #define macro with value 0 for #elif case, the #elif case test it to false. – rosshjb Jan 19 '20 at 19:40

所以如果你有这样的块:

#ifdef __linux__
  <some Linux code here>
#elif _WIN32
  <some Windows code here>
#endif

然后第二个测试与第一个明显不同 - 第一个是检查 __linux__ 是否被定义,第二个是检查符号 _WIN32 的计算结果是否为真。在许多情况下,它的行为是相同的,但不能保证这样做。

完整的等价物实际上是:

#ifdef __linux__
  <some Linux code here>
#elif defined(_WIN32)
  <some Windows code here>
#endif

这对每个人来说可能并不明显。

使用 Kerrick SB 的答案,您也可以编写相同的 #if 语句:

#if defined(__linux__)
  <some Linux code here>
#elif defined(_WIN32)
  <some Windows code here>
#endif

这使得 defined 对于 #if#elif

是相同的更加明显