使用#ifdef时是否可以使用#elif,这个做法是否合法?

26

一个谷歌无法帮我解答的简单问题。在 #ifdef 的上下文中使用 #elif 条件编译指令在 C++ 中是否合法?在 c++11 模式下,所有主要编译器(MSVC 2015/2017,clang,GCC)似乎都可以编译和正常工作,但我不确定它是否符合标准。


3
是的,这是合法的预处理器语句。在if语句后使用else-if语句。但是,请尽量不要过度依赖预处理器的魔法。 - Jesper Juhl
5
#elif 可以与 #ifdef#ifndef#if 同样地配合使用。 - Remy Lebeau
4
是的,我们可以在 #elif 中使用 #ifdef。但是,如果我们将宏定义为值为 0#ifdef 情况,那么 #ifdef 情况会被测试为 true。否则,如果我们将宏定义为值为 0#elif 情况,那么 #elif 情况将测试为 false。 - rosshjb
5
@jinbeomhong,这是因为#ifdef测试宏的存在,而不是其值。而#elif检测宏的值。 - Remy Lebeau
1
@RemyLebeau,这就是我想要的答案。我知道我可以使用#ifdef #elif,但我想知道在那种情况下#ifelif的含义是否会改变。 - Luminaire
3个回答

20

是的,语法允许在先前匹配的#if#ifdef#ifndef之后使用#elif

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)


17

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

@RemyLebeau Yes,我们可以在 #elif 中使用 #ifdef。 但是,如果我们为 #ifdef 情况定义值为 0 的宏,则 #ifdef 情况将其测试为 true。 否则,如果我们为 #elif 情况定义值为 0 的宏,则 #elif 情况将其测试为 false。 - rosshjb Jan 19 '20 at 19:40

因此,如果您有一个类似于以下的代码块:

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

那么第二个测试与第一个测试明显不同 - 第一个测试检查是否定义了__linux__,而第二个测试检查符号_WIN32是否为true。在许多情况下它们会表现相同,但不能保证总是如此。

实际上完整的等效语句是:

#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中是相同的更加明显。


好的观点,感谢您的强调。我同意对于多个分支,#if defined (...)比短形式的#ifdef更好。 - Violet Giraffe
谢谢你提供唯一正确且有意义的答案。 - ManuelSchneid3r
这就是我一直在寻找的。谢谢。 - gberth

5

是的,它是被允许的。

语法如下:

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接