这一行:
#define hash_hash # ## #
Run Code Online (Sandbox Code Playgroud)
将生成##但不是基于以下内容的未定义行为:
如果结果不是有效的预处理标记,则行为未定义.
编辑:
换句话说,扩展hash_hash会产生一个新的令牌,由两个相邻的尖锐符号组成,但这个新令牌不是##运算符.
预处理令牌的类别是:
预处理令牌分为五大类:标识符,预处理数字,字符串文字,标点符号和其他
如果没有UB,##新令牌是否属于其他类别.
注意:请花时间阅读问题和答案,甚至在低估之前.
这是标准的一个例子.## 是一个有效的预处理令牌.它是形成连接运算符的标记,就像在那里使用的那样.它在C语法中没有任何意义(在预处理之后).但它出现在标点符号列表中,同样如*或++.
由于没有语法规则可以匹配它,因此不可避免的结果是将被诊断出的语法错误.除非,它被传递给另一个串行化或忽略它的宏.
#define IGNORE(X)
#define STRINGIZE_LIT(X) #X
#define STRINGIZE(X) STRINGIZE_LIT(X)
IGNORE( hash_hash ) // OK, token is not passed to semantic analysis.
printf( STRINGIZE( hash_hash ) ); // OK, same as printf( "##" );
Run Code Online (Sandbox Code Playgroud)