【问题标题】:Can't wrap my head around Preprocessing Macros [closed]无法绕过预处理宏[关闭]
【发布时间】:2016-05-04 10:09:41
【问题描述】:

我仍在为 C 中的宏而苦苦挣扎。

所以这个应该返回-2:

#define A
#define C
int main()
{
    int i =
    #ifdef A
    #ifdef B // if A AND B is defined
        -1
    #else    // A is defined AND B is NOT defined
        -2
    #endif
    #else   // A is not defined
        -3
    #endif
    ;
    printf("%d \n", i);
}

为什么返回 -3 呢:

#define B
#define C
int main()
{
    int i =
    #ifdef A
    #ifdef C
        -1
    #else
        -2
    #endif
    #else
        -3
    #endif
    ;
    printf("%d \n", i);
}

在我看来,宏好像有自己的逻辑。

【问题讨论】:

  • 您定义 A 和 C。使用 #ifdef A 您可以测试 A 是否已定义。或者使用#ifndef A来测试是否没有定义。根据结果​​,将为 porgram 编译该部分中的代码。这通常在头文件中使用,以防止重复或定义两次。
  • 第二个打印 -3 因为 A 不再定义。 #ifdef C#ifdef A 里面,所以它甚至不会被测试。而#ifdef A#else-3
  • 您期望什么以及为什么?

标签: c macros conditional-compilation


【解决方案1】:
#include <stdio.h>
#include <stdlib.h>

#define A
#define C
int main()
{
    int i =
    #ifdef A
    #ifdef B // if A AND B is defined
        -1
    #else    // A is defined AND B is NOT defined
        -2
    #endif
    #else   // A is not defined
        -3
    #endif
    ;
    printf("%d \n", i);
}

在你的情况下,我将是 -2,因为 A 已定义但 B 未定义

【讨论】:

  • 谢谢。我编辑了我的评论以添加您的 cmets,以及另一个让我感到困惑的示例。
  • @ranpos 您没有定义 A,所以最后一个案例适用于更新的问题。想想简单的 if-else 并按照 Sourav Ghosh 的回答进行识别。那么事情就会清楚 IMO。
【解决方案2】:

首先让我相应地缩进代码以便于理解。

#define A
#define C
int main()
{
    int i =
    #ifdef A
        #ifdef B
             -1
        #else
             -2
        #endif
    #else
        -3
    #endif
    ;
    printf("%d \n", i);
}

现在,根据 #ifdef 预处理指令,引用 C11 标准,第 §6.10.1 章,

表单的预处理指令

# ifdef identifier new-line groupopt<br>
# ifndef identifier new-line groupopt`<br>

检查标识符当前是否定义为宏名称。[...]

按顺序检查每个指令的条件。如果它评估为假(零),则该组 它控制的被跳过:指令仅通过确定的名称来处理 该指令用于跟踪嵌套条件的级别;剩下的 指令的预处理标记被忽略,其他预处理标记也是如此 团体。只有控制条件评估为真(非零)的第一组是 处理。如果没有一个条件为真,并且存在#else 指令,则 由#else控制的组被处理;缺少#else 指令,所有组 直到 #endif 被跳过。

关于您的代码,

  • #ifdef A 是真的,
  • #ifdef B 是 FALSE,所以继续#else 部分,-2 包含在源代码中。
  • 跳到外部#endif

所以,经过预处理后,代码基本上看起来像

int i =-2 ;
printf("%d \n", i);

检查输出,应该是-2。

按照同样的逻辑,你可以找出其他代码的预处理输出。

【讨论】:

    【解决方案3】:

    让我试着用简单的方式回答。

    首先你是对的,宏确实有自己的逻辑,也许你明白它们是如何成为预处理器的。如果不是,那么无论它们出现在源代码的哪个位置,预处理器都是编译器读取的第一段代码。

    在编译器检查宏之后,就像您的情况一样,您的正常代码的某些部分可能对编译器变得“不可见”。现在让我们分析一下您的案例中隐藏或不可见代码的方式和内容。

    在这种情况下,您使用的是#define A#define C。这类似于布尔(但不完全是)A 和 B 已被声明为“真”或“已定义”。

    然后使用#ifdef A#ifdef: 是 if defined 的缩写形式)这里有一个 if 语句。它检查 A 是否“已定义”。在您的情况下,定义了 A,因此我们继续下一部分,可以将其视为此 if 语句中的代码。如果此处未定义 A,我们将转到第二个 #else // A is not defined

    所以现在我们检查#ifdef B,并且在您的情况下没有定义B,所以我们转到下面的第一个#else // A is defined AND B is NOT defined。因此将 I 的值设置为 -2。 #endif 就像第二个 if 语句的右大括号。接下来我们进入第二个#endif,因为定义了A,因此我们不进入第二个#else

    最后你得到的答案是-2。我检查了这段代码,它确实返回 -2。

    【讨论】:

      【解决方案4】:

      在第一种情况下,

      int i =
      #ifdef A
          #ifdef B // if A AND B is defined
              -1
          #else    // A is defined AND B is NOT defined
              -2
          #endif
      #else   // A is not defined
          -3
      #endif
      

      在这里,A 已定义,但 B 未定义。因此,将仅考虑最后一个 else 案例。因此输出将是-2

      而在第二种情况下,

      int i =
      #ifdef A
          #ifdef C
              -1
          #else
              -2
          #endif
      #else
          -3
      #endif
      

      C 已定义,但 A 不是这样,它将转到最后一个 else 条件返回 -3

      【讨论】:

      • 对于第一种情况,只定义了A和C,输出将是-2,而不是-3。
      • @tigris 感谢您的指出。已更正。
      猜你喜欢
      • 2019-06-26
      • 1970-01-01
      • 2016-09-16
      • 2015-04-15
      • 1970-01-01
      • 1970-01-01
      • 2012-02-19
      相关资源
      最近更新 更多