White space before the first preprocessing token and after the last preprocessing token composing the argument is deleted.
(我相信这也证明了参数可以在它周围有空格.)问题是,对于可以通过##运算符连接的参数,编译器应该对它的空格做什么?
我用VC试了一下,这似乎只是忽略了空格.
我认为编译器应该用空格执行连接.这可能导致无效的令牌,例如,由标识符ABC形成的“ABC”和具有空白空间作为第一令牌的参数.根据该标准,如果以这种方式形成无效令牌,则行为是未定义的.
那么对于VC之前所做的事情,它是否只是忽略空间或未定义行为的结果?
解决方法
which I believe is also an evidence proving that arguments can have spaces around it
不,实际上它只强化了标准的规定,即每个宏参数都是一系列预处理标记(C2011,6.10.3 / 11).源文件中的空格分隔预处理标记;空白行不是自己预处理令牌.
您引用的标准部分可能会混淆,因为它混合了级别 – 源文件的字符序列,空白所属的字符序列,以及源序列的初始标记化产生的预处理标记序列.实际上,字符串化对于相邻令牌是否被源字符序列中的空格分隔很敏感,但任何此类空白的细节根本不重要 – 在字符串化时,相邻的白色空间分隔的标记由单个空格分隔结果字符串中的字符.
这并不意味着预处理令牌可以以空格开头或结尾.它不能;有关详细信息,请参阅标准的第6.4节.给定实现如何满足字符串化的规范必然是特定于实现的,但是实现可以这样做的一种方式将涉及为每个预处理标记维护布尔标志,该标记描述该标记是否在空白空间的源序列之前和/或之后.这些细节与解释标准为结果指定的内容无关,但是,对于字符串化运算符和标记粘贴运算符都没有.
for arguments that would be concatenated by ## operator,what should compiler do about its spaces?
当##运算符(或#运算符)发挥作用时,编译器已经完成了(直接)对源文件中出现的空格字符所做的一切,在将源标记化为预处理标记期间考虑它们. .宏参数是预处理标记的序列,并且只有这些标记可以是字符串或字符文字或标题名称的范围内它们可能包含空格.此外,该标准规定:
If,in the replacement list of a function-like macro,a parameter is immediately preceded or followed by a
##
preprocessing token,the parameter is replaced by the corresponding argument’s preprocessing token sequence […]
(C2011,6.10.3.3/2;重点补充)
再一次,空格运行不是预处理标记.宏扩展和#和##运算符处理预处理标记序列的级别.空格仅在令牌内部表示在此级别.来自源文件的非预处理标记内部的空格仅在预处理标记序列中间接且不确定地表示.