【问题标题】:How C preprocessor works?C 预处理器如何工作?
【发布时间】:2014-11-12 07:01:32
【问题描述】:

C 预处理器如何处理多个宏?我在这里和谷歌也搜索过,但无法理解应该遵循的确切规则。以下代码:

#define ABC xYz
#define xYz ABC
int main()
{
    int ABC;
    int xYz;    
}

在 gcc 上,像这样生成 preprocessor.i:

# 1 "preprocessor.c"
# 1 "<command-line>"
# 1 "preprocessor.c"


int main()
{
 int ABC;
 int xYz;
}

这里似乎什么都没有被替换。和其他代码:

#define ABC kkk
#define xYz ABC
int main()
{
    int ABC;
    int xYz;    
}

生成如下输出:

# 1 "preprocessor.c"
# 1 "<command-line>"
# 1 "preprocessor.c"


int main()
{
 int kkk;
 int kkk;
}

那么这一切是如何发生的。

【问题讨论】:

    标签: c gcc c-preprocessor


    【解决方案1】:

    第一种情况的行为是正确的,因为宏一旦在扩展中使用过一次,就不能再次使用。因此,预处理器首先将int ABC; 中的ABC 转换为int xYz;,然后将xYz 转换回ABC,但由于这两个宏都使用过一次,因此无法进行进一步的转换。

    当然,第二个代码的行为也正确。 int ABC; 直接变成int kkk;int xYz; 变成int ABC; 然后变成int kkk;

    您可以查看How many passes does the C preprocessor make? 了解更多信息。

    预处理器是否一个接一个地进行宏替换,例如首先完成与#define ABC xYz 对应的扩展,然后执行#define xYz ABC,还是一次性处理两个宏?如果是第一种情况,那么输出应该是int ABCint ABC

    定义宏的顺序无关紧要。预处理器对输入进行标记,并且对于每个符号,它会查看是否定义了宏。如果有宏,它会应用宏扩展,然后将其标记为“已使用”(用于当前令牌扩展)。然后它重新扫描替换文本,再次查找标记,并再次应用宏(除非它们被标记为“已使用”)。 “标记为已使用”可防止宏扩展中的无限递归。当它完成重新扫描替换文本时,所有“已使用”的宏都会再次标记为“未使用”。

    【讨论】:

    • Thakns 回复但我没听明白。预处理器是否像第一个对应于#define ABC xYz 一样进行微替换,然后它会用于#define xYz ABC 或者它处理两个微一气呵成。如果 first 是这种情况,那么输出应该是 int ABC 和 int ABC。
    猜你喜欢
    • 1970-01-01
    • 2017-07-07
    • 1970-01-01
    • 2021-06-05
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 2011-07-01
    相关资源
    最近更新 更多