预处理器是否扩展用引号括起来的宏?
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 预处理器对字符文字的内容执行宏扩展。我不知道有任何实现在这方面违背我的期望。
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 预处理器对字符文字的内容执行宏扩展。我不知道有任何实现在这方面违背我的期望。