6
#define B 100+B
main()
{
    int i= B;
}

我知道这是错误的,但出于好奇,当我编译它时,我得到了这个奇怪的错误:

“B 未在此范围内声明”。

为什么会这样?如果此错误是因为编译器在替换宏后删除了宏,那么以下代码如何正常工作,当B必须在对A可用之前被删除时?

#define B 100
#define A 100+B
main()
{
    int i= B;
    int j =A;
}
4

3 回答 3

14

这是预处理器的输出:

gcc -E x.c
# 1 "x.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "x.c"

main()
{
    int i= 100+B;
}

如您所见,它进行了替换。现在是因为没有B声明而失败的编译步骤。

其他代码很好,输出如下:

main()
{
    int i= 100;
    int j =100+100;
}
于 2012-08-05T18:09:32.850 回答
9

宏扩展不是递归完成的,如果宏名称出现在替换文本中,则不会再次扩展。所以随着

#define B 100 + B

替换B产生令牌序列100 + B并且B不会再次扩展(如果是,您将有无限递归)。所以编译器会B在预处理器完成后看到对未声明变量的引用。

但在

#define B 100
#define A 100 + B

当宏A展开时,宏名称会B出现在替换文本中。然后B展开,编译器看到100 + 100哪些不包含对未声明变量的引用。

于 2012-08-05T18:13:41.523 回答
0

宏替换是简单的文本操作。您可以通过简单的逐步编译来调试此类问题。

使用 cc -E 文件名.c -O 文件名.i

用于生成扩展的 c 代码

vi filename.i 用于读取纯/扩展的 c 代码

于 2012-08-05T18:18:24.897 回答