预处理器是否扩展用引号括起来的宏?

Do preprocessors expand macros surrounded by quotation marks?

cpp 和 fpp 等常见的预处理器是否展开用一对引号括起来的宏?

我试过下面的代码同时使用cpp和fpp,似乎引号内的宏没有被展开。但是,我没有在任何有关 cpp 或 fpp 的文档中找到此规则。任何人都可以指导我一些文档,以便我可以确定这种行为吗?谢谢

#define X Y
X
"X"
'X'

对于 C(不知道 Fortran 但可能相同):

Do processors expand macros surrounded by quotation marks?

没有

当宏的标识符是字符串文字"")或字符常量[的一部分时,宏不会展开=32=] ('')。然后宏 identifier/name 成为字符串 literal/character 常量的一部分。

"X" - 这是字符 'X' + '[=14=]'.

字符串文字

'X' - 这是字母 X.

字符常量

另一种观点是:预处理器替代了tokens/identifiers,它是有用的。文字(数字或字符串)不是标识符,替换它是无用的,而且风险很大。

另一个答案提到符合 C 的预处理器应该不会替换文字字符串。为了更进一步,我尝试编译以下程序:

#define 12 13
#include <stdio.h>

main() {
  printf("%i\n", 12);
}

结果(gcc 版本 8.3.0,Debian 8.3.0-6)是:

test.c:1:9: error: macro names must be identifiers
 #define 12 13
         ^~

我认为这表明预处理器想要使用标识符。

Do common preprocessors like cpp and fpp expand macros surrounded by a pair of quotation marks?

C 语言规范描述了符合规范的 C 预处理器的行为。 C 的实际标准不是免费提供的,但您可以获得最新草案的副本。例如,对于 C18,您可以参考 N2176。特别是,您应该查看 5.1.1.2 和 6.10.3 节。特别相关的是第 6.10.3 节中的脚注 173:

Since, by macro-replacement time, all character constants and string literals are preprocessing tokens, not sequences possibly containing identifier-like subsequences (see 5.1.1.2, translation phases), they are never scanned for macro names or parameters.

(基本相同的文本也出现在标准的早期版本中。)

那么,C 的底线是没有,符合标准的 C 预处理器不会对字符串文字或字符常量的内容执行宏替换。


Fortran 的情况不太明确,因为 Fortran 语言规范没有定义预处理设施。语言本身内置了一个 include 语句,但 Fortran 从业者通常不会考虑使用它来进行预处理。 Fortran 源代码很少依赖预处理功能,例如宏扩展或条件编译。

尽管如此,某些 Fortran 实现确实提供了预处理工具,有时可作为名为 fpp 的独立程序使用。您需要查阅特定 fpp 的文档以了解详细信息,但通常这些是 C 预处理器对 Fortran 语法的改编。因此,no,我不希望 Fortran 预处理器对字符文字的内容执行宏扩展。我不知道有任何实现在这方面违背我的期望。