C代码中`#define`的位置是否重要?

时间:2017-01-03 07:06:59

标签: c compiler-errors c-preprocessor

我的印象是#define#include可以写在代码中的任何位置,只要它们在预处理器处理宏之前不会产生任何语法错误它被提取给编译器。

我运行了以下代码:

#include <stdio.h>

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

它产生了以下错误:

  

prog.c:在函数&#39; main&#39;:prog.c:4:13:错误:&#39; A&#39;未申报的(首先   在这个功能中使用)        int B = A;                ^ prog.c:4:13:注意:每个未声明的标识符仅针对它出现的每个函数报告一次

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

#include <stdio.h>

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

不确定我在这里缺少什么,但为什么编译器会出现这样的错误&#34;未声明的A&#34;?

当预处理器读取行#define A 4时,它会从后续代码行开始用A 替换任何4吗?< / p>

4 个答案:

答案 0 :(得分:9)

C文件在预处理阶段和编译阶段从上到下进行解析。 (注意:由于 MSalters 指出,每个阶段在顶部单独启动)。

预处理器无法替换A,直到看到令牌define d。

  

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

是。你不会错过很多。

答案 1 :(得分:1)

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

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

预处理行以空格开头,后跟#。所有未启动的行都被视为文本代码行。

根据某些条件选择不同的参数时,在函数内部包含#define是很常见的,例如

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

或者您可以使用#include来初始化类似

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

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

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

#define会将对象宏static插入到具有值nil的预处理器环境中,并且此对象在行#define static#undef之间有效。

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:-2)

你已经在大括号中定义了'A',所以'A'的生命将仅限于那些大括号(仅适用于主循环)。大括号代码按顺序执行,你在定义之前使用'A'。