我们可以在很多行中编写宏而不用反斜杠吗?
我在CPP手册中看到了一些例子,我们可以在没有反斜杠的情况下在多行中编写宏体。
#define strange(file) fprintf (file, "%s %d", ... strange(stderr) p, 35)
输出:
fprintf (stderr, "%s %d", p, 35)
它们是特殊情况,如参数宏中的指令还是只允许#define?
对于include指令如果我没有错,它必须总是在一行上声明。
编辑:
来自https://gcc.gnu.org/onlinedocs/cpp/Directives-Within-Macro-Arguments.html
3.9宏观论证中的指令
有时,在宏的参数中使用预处理程序指令很方便 。 C和C ++标准声明在这些情况下的行为是未定义的。 GNU CPP处理宏参数中的任意指令的方式与处理指令的方式完全相同,类似函数的宏调用不存在。
如果在宏调用中重新定义了该宏,则新定义会在参数预扩展时及时生效,但原始定义仍用于参数替换。 这是一个病态的例子:
#define f(x) xx f (1 #undef f #define f 2 f)
扩展到
1 2 1 2
用上面描述的语义。
这个例子很多。
没有反斜杠换行符的多行宏定义
由于在翻译阶段3中注释被替换为空格:
- 源文件被分解为预处理标记7)和空白字符序列(包括注释)。 源文件不应以部分预处理标记或部分注释结束。 每个注释都被一个空格字符替换。 保留换行符。 是否保留或替换为新行以外的每个非空白字符序列是由实现定义的。
并且预处理器作为阶段4运行:
- 执行预处理指令,扩展宏调用,并执行
_Pragma
一元运算符表达式。 如果通过标记连接(6.10.3.3)生成与通用字符名称的语法匹配的字符序列,则行为未定义。#include
预处理指令使得命名的头文件或源文件以递归方式从阶段1到阶段4进行处理。 然后删除所有预处理指令。
编写像这样的多行宏是可能的,但很荒谬:
#include #define possible_but_absurd(a, b) /* comments */ printf("are translated"); /* in phase 3 */ printf(" before phase %d", a); /* (the preprocessor) */ printf(" is run (%s)\n", b); /* but why abuse the system? */ int main(void) { printf("%s %s", "Macros can be continued without backslashes", "because comments\n"); possible_but_absurd(4, "ISO/IEC 9899:2011,\nSection 5.1.1.2" " Translation phases"); return 0; }
在运行时,指出:
Macros can be continued without backslashes because comments are translated before phase 4 is run (ISO/IEC 9899:2011, Section 5.1.1.2 Translation phases)
宏定义中的反斜杠 – 换行符
翻译阶段1和2也有些相关:
- 如果需要,物理源文件多字节字符以实现定义的方式映射到源字符集(引入行尾指示符的换行符)。 Trigraph序列由相应的单字符内部表示替换。
三字符替换在名义上是相关的,因为??/
是反斜杠的三字形。
- 将删除紧跟着换行符的每个反斜杠字符(
\
)实例,拼接物理源行以形成逻辑源行。 只有任何物理源线上的最后一个反斜杠才有资格成为这种拼接的一部分。 非空的源文件应以换行符结尾,在进行任何此类拼接之前,该换行符不应立即以反斜杠字符开头。
这告诉您,在运行阶段4(预处理器)时,宏定义位于单个(逻辑)行上 – 已删除尾部反斜杠 – 换行符组合。
标准指出阶段“好像” – 编译器的行为必须好像经历了不同的阶段,但许多实现并没有正式将它们完全分开。
避免GCC扩展
扩展示例(引自GCC手册)的调用遍布多行,但定义严格在一行。 (这不是GCC扩展,而是完全标准的行为。)
请注意,如果您是远程理智的,那么您将忽略在宏的调用中放置预处理指令的可能性(示例中为#undef
和#define
)。 它是GCC扩展,完全不可移植。 该标准表明行为未定义。
附件J.2未定义的行为
- 宏参数列表中有一系列预处理令牌,否则它们将充当预处理指令(6.10.3)。
不,这是不可能的。 在每行之前处理行拼接要么被解释为代码文本行或预处理指令,并且在预处理器步骤4(有效预处理算法)内部没有到达行拼接,因为它们之前已被消除。
#define strange(file) fprintf (file, "%s %d",
你的define被解释为一个函数宏,它使预处理fprintf (stderr, "%s %d",
替换call strange(stderr)
fprintf (stderr, "%s %d",
,.预处理器不知道C语法和语义,它是另一种语言,非turing -完成。
不行,你不可以。 必须使用反斜杠作为多行预处理器宏的行继续转义字符。