繁体   English   中英

C预处理器宏参数,末尾有空格用于连接?

[英]C preprocessor macro arguments with space at the end for concatenating?

根据C11标准,类函数宏的参数可以在其预处理标记序列的开头或结尾包含空格。 对于正常更换,这种空间没有任何影响。 对于字符串化,应忽略空格,如6.10.3.2.2中所述

第一个预处理标记之前和构成参数的最后一个预处理标记之后的空格被删除。

(我相信这也证明了参数可以在它周围有空格。)问题是,对于可以通过##运算符连接的参数,编译器应该对它的空格做些什么?

我用VC ++试了一下,似乎只是忽略了空格。

我认为编译器应该用空格执行连接。 这可能导致无效的令牌,例如,由标识符ABC形成的“ABC”和具有空白空间作为第一令牌的参数。 根据该标准,如果以这种方式形成无效令牌,则行为是未定义的。

那么对于VC ++之前所做的事情,它是否只是忽略空间或未定义行为的结果?

我相信这也证明了论证可以有空间

不,实际上它只强化了标准的规定,即每个宏参数都是一系列预处理标记 (C2011,6.10.3 / 11)。 源文件中的空格分隔预处理标记; 空白行不是自己预处理令牌。

您引用的标准部分可能会引起混淆,因为它混合了级别 - 源文件的字符序列,空白所属的字符序列,以及源序列的初始标记化产生的预处理标记序列。 实际上,字符串化对于相邻令牌是否被源字符序列中的空格分隔很敏感,但任何此类空白的细节根本不重要 - 在字符串化时,相邻的白色空间分隔的标记由单个空格分隔结果字符串中的字符。

这并不意味着预处理令牌可以以空格开头或结尾。 它不能; 有关详细信息,请参阅标准的第6.4节。 给定实现如何满足字符串化的规范必然是特定于实现的,但是实现可以这样做的一种方式将涉及为每个预处理标记维护布尔标志,该标记描述该标记是否在空白空间中在源序列中之前和/或之后。 这些细节与解释标准为结果指定的内容无关,但是,对于字符串化运算符和标记粘贴运算符都没有。

对于将由##运算符连接的参数,编译器应该对其空格做什么?

##运算符(或#运算符)发挥作用时,编译器已经完成了(直接)对源文件中出现的空格字符所做的一切,在将源标记化为预处理标记期间考虑它们。 。 宏参数是预处理标记的序列,并且只有这些标记可以是字符串或字符文字或标题名称的范围内它们可能包含空格。 此外,该标准规定:

如果在类函数宏的替换列表中,参数紧跟在##预处理标记之前或之后,则参数将被相应参数的预处理标记序列替换[...]

(C2011,6.10.3.3/2;重点补充)

再一次,空格运行不是预处理标记。 宏扩展和###运算符处理预处理标记序列的级别。 空格仅在令牌内部表示在此级别。 来自源文件的非预处理标记内部的空格仅在预处理标记序列中间接且不确定地表示。

6.10.3.3/3

在重新检查替换列表以替换更多宏名称之前,删除替换列表中的##预处理标记的每个实例(不是来自参数),并将前面的预处理标记与以下预处理标记连接起来。

所以##连接两个预处理标记。 它们的参数是否包含空格无关紧要。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM