在 C++11 2.5 预处理标记 [lex.pptoken] 中:
如第 16 条所述,在翻译阶段 4 的某些情况下,空白(或不存在)不仅仅是预处理令牌分离。
这是指什么情况?
在第 4 阶段,有几次空白很重要:
每个预处理指令都以#
“源文件中的第一个字符......或者包含至少一个换行符的空格”开头。每个预处理指令都以换行符结尾。
在类似函数的宏定义中,开始参数列表的左括号必须紧跟在命名宏的标识符之后。它们之间不能有空格。
例如,该指令#define F()
定义了一个扩展为空的类似函数的宏,而该指令#define F ()
定义了一个扩展为()
.
#
当在宏替换期间对运算符进行评估时,在字符串化期间会考虑空格。要字符串化的标记之间的空格序列在生成的字符串文字中折叠为单个空格。
例如,字符序列f(x)
被字符串化为"f(x)"
,但字符序列f ( x )
被字符串化为"f ( x )"
,即使宏替换后两者在语义上没有区别。
请注意,在第 2 阶段消除了转义的换行符,并且在第 3 阶段将每个注释替换为单个空格字符。这两者都发生在第 4 阶段之前,因此在第 4 阶段期间,转义的换行符不算作新的-line 和注释与空格字符无法区分。
第 16 条规定:
除了在预处理期间的某些情况下,所有空格都是等效的(例如,请参见cpp.stringize中的 # 字符串文字创建运算符 )。
您可以在此处阅读有关# 运算符 [ccp.stringize] 的信息。以下是相关信息:
如果在替换列表中,一个参数前面紧跟一个
#
预处理标记,则两者都被一个字符串文字预处理标记替换,该预处理标记包含对应参数的预处理标记序列的拼写。参数的预处理标记之间每次出现的空白都会成为字符串文字中的单个空格字符。删除第一个预处理标记之前和包含参数的最后一个预处理标记之后的空白。否则,参数中每个预处理标记的原始拼写将保留在字符串文字中,但生成字符串文字和字符文字的拼写的特殊处理除外:\
在字符文字或字符串文字(包括定界字符)的每个字符"
之前插入字符。如果导致的替换不是有效的字符串文字,则行为未定义。和运算符的评估顺序未指定。\
"
#
##