为什么宏调用另一个宏显示错误?

时间:2015-09-04 16:36:37

标签: c

我编写了以下程序,并且令人惊讶地显示了编译错误

'X' undeclared in exapansion of macro.

c中的代码是:

#include<stdio.h>
#define X (4+Y)
#define Y (X+3)

int main()
{
    printf("ds", "ds");
    printf("%d\n", 4*X+2);
    return 0;
}

我接受这会导致一种无限的宏替换,但如果这是一个错误,那应该是一个运行时错误(真的说完全没有错误)。我对么?如果没有,请纠正我并解释我在哪里弄错了?

编辑:我很惊讶以下代码可以完美运行:

#include<stdio.h>
#define X (4+Y)
#define Y 4

int main()
{
    printf("ds", "ds");
    printf("%d\n", 4*X+2);
    return 0;
}

2 个答案:

答案 0 :(得分:3)

在扩展宏时(包括间接通过另一个宏),C预处理器不会扩展宏。因此,在Y扩展中扩展X时,预处理器会按原样保留X,因此会得到未定义的变量错误。

这不仅可以防止无限扩展循环,还提供了一个有用的功能。例如,假设您要编写一个“包装”现有函数的宏:

#define my_function(x, y) do { \
  fputs("Calling my_function\n", stderr); \
  my_function(x, y); \
while(0);

my_function未在其自身扩展中扩展的事实使得可以使用具有相同名称的宏来包装函数,从而避免源修改。

对于任何通过语言的律师,该标准规定(§6.10.3.4/ 2):

  

如果在替换列表的扫描期间(不包括源文件的其余预处理标记)找到要替换的宏的名称,则不会替换它。此外,如果任何嵌套替换遇到要替换的宏的名称,则不会替换它。这些未替换的宏名称预处理令牌不再可用于进一步替换,即使它们稍后(重新)检查其中宏名称预处理令牌将被替换的上下文中。

答案 1 :(得分:0)

使用 gcc -E -o main.I main.c 在main.c文件中创建代码的.I文件,然后我们得到一个文件,其中包含如下

int main()
{
printf("ds", "ds");
printf("%d\n", 4*(4+(X+3))+2);
return 0;
}

因此宏只是替换了值。因此,在X扩展中扩展Y时,预处理器将X保持原样。 因此,当X未定义时会发生错误。