我在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) x x f (1 #undef f #define f 2 f)
扩展为
1 2 1 2
使用上述语义。
这个例子有很多行。
答案 0 :(得分:3)
由于在翻译阶段3中注释被替换为空格:
- 源文件被分解为预处理标记 7)和序列 空格字符(包括注释)。源文件不得以a结尾 部分预处理令牌或部分注释。每条评论都被替换为 一个空格字符。保留换行符。是否每个都是空的 新行以外的空白字符序列被保留或替换为 一个空格字符是实现定义的。
醇>
并且预处理器作为阶段4运行:
- 执行预处理指令,扩展宏调用,以及 执行
醇>_Pragma
一元运算符表达式。如果是一个字符序列那个 匹配通用字符名称的语法由token生成 连接(6.10.3.3),行为未定义。#include
预处理。#include <stdio.h> #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; }
指令导致从阶段1处理命名的头文件或源文件。 通过阶段4,递归。然后删除所有预处理指令。
编写像这样的多行宏是可能的,但是很荒谬:
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序列被替换为 相应的单字符内部表示。
醇>
三字符替换在名义上是相关的,因为\
是反斜杠的三字符。
- 反斜杠字符(
醇>#undef
)的每个实例后面紧跟一个换行符 删除字符,拼接物理源行以形成逻辑源行。 只有任何物理源代码行的最后反斜杠才有资格成为其中一部分 这种拼接。非空的源文件应以换行符结尾, 在任何此类之前不得立即使用反斜杠字符 拼接发生。
这告诉您,在第4阶段(预处理器)运行时,宏定义位于单个(逻辑)行上 - 尾部反斜杠 - 换行符组合已被删除。
该标准指出,这些阶段似乎是&#39; - 编译器的行为必须好像经历了不同的阶段,但许多实现并没有正式将它们完全分开。
扩展示例(引自GCC手册)的调用遍布多行,但定义严格在一行。 (这不是GCC扩展,而是完全标准的行为。)
请注意,如果您远程理智,您将忽略在宏的调用中放置预处理指令的可能性(示例中为#define
和<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
)。它是GCC扩展,完全不可移植。该标准表明行为未定义。
附件J.2未定义的行为
- 在宏参数列表中有一系列预处理令牌,否则它们将充当预处理指令(6.10.3)。
答案 1 :(得分:1)
不,这是不可能的。在每行之前处理行拼接作为代码文本行或预处理指令,并且在预处理器中,步骤编号4(有效预处理算法)不会到达任何行拼接,因为它们之前已被删除。
#define strange(file) fprintf (file, "%s %d",
您的定义被解释为一个函数宏,它使预处理器将strange(stderr)
替换为fprintf (stderr, "%s %d",
。预处理器不了解C语法和语义,它是另一种语言,非turing-complete。
答案 2 :(得分:0)
没有。你不可以。您必须使用反斜杠作为多行预处理器宏的行继续转义字符。