为什么宏定义“ #define yyparse ol_parser_parse”可以工作?

时间:2019-04-20 23:37:33

标签: c

之前,我没有仔细阅读yacc生成的代码。现在,我看到了一个这样的代码片段:

#define yyparse ol_parser_parse

我知道 yyparse 的定义如下:

int yyparse (void) 

因此,此宏定义应解释为:代码中的每个“ ol_parser_parse”都将替换为“ yyparse”。我写了一些测试代码:

#include <stdio.h>
#define yyparse ol_parser_parse
void yyparse()
{
    printf("hello world\n");
}
void main()
{
   ol_parser_parse();
}

成功了! 但是根据关于"macro definition"的定义:

#define <identifier>(<parameter list>) <replacement token list>

对此我感到困惑。谁能帮我解释一下?预先感谢!

1 个答案:

答案 0 :(得分:2)

这是执行替换后编译器看到的代码:

#include <stdio.h>

void ol_parser_parse()
{
    printf("hello world\n");
}
void main()
{
   ol_parser_parse();
}

在这一点上没有什么神秘的。 #define之后的每一行上的每个“ yyparse”实例都变成“ ol_parser_parse”。

在文档中 identifier 表示要替换的东西,而替换令牌列表是您要替换的东西。您也可以使用参数,例如:

#define TIMES_TWO(n) ((n) * 2)

您可以在哪里做

int x = TIMES_TWO(3);

等同于:

int x = ((3) * 2);

在多余的括号中,因此您可以执行此操作而不会弄乱操作顺序:

int x = TIMES_TWO(1 - 5);

如果没有括号,它将显示为:

int x = 1 - 5 * 2;

哪个计算为1 - 10,这不是您想要的。

有效使用#define来隐藏否则很难看的实现细节是一门艺术。如果可以使用ol_parser_parse宏,则不必担心名称yyparser。这使实现者可以自由地重命名该函数和相应的宏,而无需破坏所有代码。