2

当我运行以下代码时,

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

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

I am getting the following output: 
Error: Undefined symbol 'X'

有人可以解释一下输出吗?

4

3 回答 3

6

这是因为宏期望和参数,因为它用括号定义。您需要将其定义为

#define X 4+Y#define Y X+3。然后你会因为宏中的循环定义而遇到另一个麻烦。

正如德鲁建议的那样,更正确的是;当定义宏时示例可编译时,通常将括号放在表达式周围以确保预期的运算符优先级。

所以你最好的镜头是:

#define X (4+Y)
#define Y (X+3)

非常接近您的初始示例,只是宏名称与其定义之间的空格字符。但是,由于循环引用,仍然无法正确扩展宏。

如何检查发生了什么:

您可以使用gcc -E,它输出一个预处理文件。它会产生大量输出,所以我使用了tail. 我也曾经2>err将错误流重定向到一个文件,所以输出很清楚。

luk32:~/projects/tests$ gcc -E ./cyclic_macro_with_no_spaces.c 2> err | tail -n 6

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


luk32:~/projects/tests$ gcc -E ./cyclic_macro.c 2> err | tail -n 6

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

在第一个示例中,X根本没有扩展。而在后者中,两个宏都得到了扩展,尽管只有一个。给出与杰弗里在他的回答中提出的相同的输出。

无论没有空格是错字还是有undefined symbol 'X'. 出于不同的原因,可以通过分析err文件进行跟踪。

于 2013-07-24T15:31:29.460 回答
5

如果宏被保留为无效的类函数宏,它们根本不会被扩展,因为你没有用括号调用它。所以 X 永远不会被预处理器替换为任何东西,这就是Undefined symbol 'X'您的示例代码中出现的原因。

如果你想扩展它,你必须用这样的括号来调用它:

printf("%d",4*X()+2);

但是,当预处理为4+Y并且X+3不是有效的宏参数名称时,这只会出错。

如果您的答案有所纠正,以便这些定义是正确的定义,而不是类似函数的宏,即:

#define X (4+Y)
#define Y (X+3)

您在定义之间有一个循环引用...

X -> Y -> X... 等等。

由于它只会扩展一次宏,因此它正在扩展为

printf("%d",4*(4+(X+3))+2);

这就解释了为什么 X 在这个用例中是未定义的符号。

于 2013-07-24T15:30:07.370 回答
1

你错过了空间

#define X (4+Y)
#define Y (X+3)
于 2013-07-24T15:30:07.400 回答