__LINE__在宏中使用时的行为

时间:2019-05-17 20:20:04

标签: c gcc c-preprocessor

__LINE__为什么根据在类似函数的宏还是常规函数中使用它来进行评估?

例如:

#include<stdio.h>

#define A() printf("%d\n",__LINE__);

int main(void) {
/* 6 */  A();
/* 7 */  A(
/* 8 */    );
/* 9 */  printf("%d\n",__LINE__
/* 10 */  );
}

我希望得到:

6
7
9

但是相反,我们得到了(使用clang-1000.10.44.4):

6
8
9

请注意,在类似于函数的宏中,如何分散到第7和8行,而不是第一行,而是最后占用的行。

GCC的文档提供了详细信息:https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html

我为什么要关心?我正在编写一个解析器,该解析器需要以与A将返回的内容对齐的方式来查找宏__LINE__的所有实例的行号。由于需要解析可能转义的参数,因此很难找到宏用法的 last 行,而不是 first

1 个答案:

答案 0 :(得分:9)

C实现在看到结束A()之前不会替换)宏。 )出现在第8行,因此是发生宏替换的地方。

__LINE__的宏替换方面的详细信息未由C标准明确指定。您可能不应在此依赖特定的行为。当然C实现不能替换A()宏,因为它只读到第7行,因为它尚不知道会发生什么。一旦看到结束),那么当它替换宏时,它可能会考虑替换令牌出现在第7行或第8行或某种混合上-C标准对此并不专门;此时,行号在很大程度上与C语义无关,并且__LINE__宏在很大程度上方便了调试和其他开发工作,而不是生产程序的功能(尽管它们可能有一些用途)。

printf中,C实现在看到行尾时便识别出__LINE__宏。 (实际上,解析更复杂;输入已被标记化,但是效果是在检查行尾字符时可以识别__LINE__标记。)它位于第9行,因此被替换了由9。它是printf的参数这一事实是无关紧要的。 C实现没有printf进程来替换第9行上的__LINE__令牌;他们不会互动。