末尾带有 space 的 C 预处理器宏参数用于连接?

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

根据 C11 标准,类函数宏的参数可以在其预处理标记序列的开头或结尾包含白色space。对于正常的替换,这种space是没有作用的。对于字符串化,应该忽略 spaces,如 6.10.3.2.2

中所述

White space before the first preprocessing token and after the last preprocessing token composing the argument is deleted.

(我相信这也是证明参数周围可以有 space 的证据。)问题是,对于将由 ## 运算符连接的参数,编译器应该如何处理它spaces?

我用 VC++ 试过了,它似乎忽略了 spaces。

我认为编译器应该执行与 whitespace 的连接。这可能会导致无效的令牌,例如,"ABC " 由标识符 ABC 和一个以白色 space 作为第一个令牌的参数组成。根据标准,如果以这种方式形成无效令牌,则行为未定义。

那么对于VC++之前提到的所做的事情,是简单地忽略space的结果还是未定义行为的结果?

6.10.3.3/3

before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.

因此 ## 连接两个预处理标记。从中获取的参数是否包含空格无关紧要。

which I believe is also an evidence proving that arguments can have spaces around it

不,事实上它只是强化了标准的规定,即每个宏参数都是一个预处理标记序列 (C2011, 6.10.3/11)。源文件中的白色space分隔预处理标记; whitespace 的运行本身并不是预处理标记。

您引用的标准部分可能令人困惑,因为它混合了级别——源文件的字符序列,whitespace 所属,以及由初始标记化产生的预处理标记序列源序列。事实上,字符串化对源字符序列中相邻的标记是否由 whitespace 分隔很敏感,但任何此类 whitespace 的细节根本无关紧要——在字符串化时,相邻的标记是white-space 分隔在结果字符串中由单个 space 字符分隔。

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

for arguments that would be concatenated by ## operator, what should compiler do about its spaces?

## 运算符(或 # 运算符)开始发挥作用时,编译器已经完成了它会(直接)对出现的 space 个字符执行的所有操作在源文件中,通过在将源标记化为预处理标记期间考虑它们。宏参数是预处理标记的序列,并且只有在这些标记可能是字符串或字符文字或 header 名称的情况下,它们才可能包含 whitespace。此外,标准规定:

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;已强调)

再次强调,whitespace 运行不是预处理标记。宏扩展和 ### 运算符处理预处理标记序列并在其级别进行操作。 Whitespace 仅在代币内部在此级别表示。来自源文件的非预处理标记内部的白色space在预处理标记序列中仅间接且不确定地表示。