【问题标题】:Does the position of `#define` in C code matter?`#define` 在 C 代码中的位置重要吗?
【发布时间】:2017-01-03 07:06:58
【问题描述】:

我的印象是 #define#include 可以写在我们代码的任何地方,只要它们在预处理器处理宏之前不会产生任何语法错误,然后再将其提取到编译器.

我运行了以下代码:

#include <stdio.h>

int main(void) {
    int B = A;
    #define A 4
    printf("%d", B);
    return 0;
}

它产生了以下错误:

prog.c:在函数'main'中:prog.c:4:13:错误:'A'未声明(首先 在这个函数中使用) 诠释 B = A; ^ prog.c:4:13: 注意:每个未声明的标识符对于它出现的每个函数只报告一次

但是当我这样做时,它会起作用!

#include <stdio.h>

int main(void) {
    #define A 4
    int B = A;
    printf("%d", B);
    return 0;
}

不确定我在这里遗漏了什么,但为什么编译器会给出这样的错误“未声明的 A”?

这样当预处理器读取#define A 4 行时,它会开始用4 替换任何A 从后续代码行

【问题讨论】:

  • 没有。将预处理器指令放在哪里绝对很重要。此外,虽然编译时无错误是有效程序的必要条件,但肯定不是充分条件。

标签: c compiler-errors c-preprocessor


【解决方案1】:

C 文件在预处理阶段和编译阶段都从上到下进行解析。 (注意:正如 MSalters 所指出的,每个阶段都从顶部单独开始)。

预处理器在看到令牌defined 之前不会替换A

这样当预处理器读取#define A 4 行时,它会 从后续代码行中开始用 4 替换任何 A?

是的。你并没有错过太多。

【讨论】:

  • 也许明确一点:预处理阶段从上到下运行,然后编译阶段才从顶部开始。
  • @MSalters - 已添加。感谢您的改进建议。
【解决方案2】:

预处理指令的位置无关紧要,因为预处理器不知道 C 语法。

预处理器(即文件分析的第四阶段)也可以预处理其他语言。

预处理行以空格开头,后跟#。所有没有开始的行都被认为是文本代码行。

当您根据某些条件选择不同的参数时,通常在函数中包含#define,例如

f(
#if cond1
a
#elif cond2
b
#else
c
#endif
)

或者你可以使用 #include 来初始化这样的数组

int[] a = {
             #include data-file
          }

或者您可以使用#define 根据某些条件更改语法。例如,当arch为真时,不考虑静态关键字static

f()
{
#if arch
#define static
#endif
static int x;
...
#undef static
}

#define 将在预处理器环境中插入对象宏static,其值为nil,并且该对象在#define static#undef 行之间有效。

在您的情况下,您在使用变量 A 之后定义它,之前 1 行。

【讨论】:

    【解决方案3】:

    没有。您可以在任何您想这样做的地方定义和取消定义。但是,您需要在使用宏之前定义它们。您在声明宏之前已经使用了它。

    预处理器没有“水晶球”,也没有前瞻。如果您定义了一个宏,该宏将从该点开始有效,直到文件结束或找到#undef 标记。

    【讨论】:

      【解决方案4】:

      您已经在大括号中定义了“A”,因此“A”的生命周期将仅限于该大括号(仅适用于主循环)。大括号中的代码按顺序执行,并且您在定义之前使用了“A”。

      【讨论】:

      猜你喜欢
      • 2020-06-11
      • 2018-02-19
      • 1970-01-01
      • 2015-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-06
      相关资源
      最近更新 更多