Ard*_*der 3 c c++ concatenation token c-preprocessor
为什么会出现以下错误?
#include <iostream>
#define concatenate(t1, t2) t1 ## t2 // Concatenate token1 and token2
int main()
{
int myVar = 22;
std::cout << concatenate(my, Var); // Compiles fine and outputs the value of myVar
concatenate(/, /) So I thought that this would be a comment but this is a compile-time error
// error: pasting "/" and "/" does not give a valid preprocessing token
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我认为这concatenate(/, /)会告诉预处理器用 a 替换它,//然后当它进一步解析时,整行将被解释为注释。
在这种情况下实际发生了什么?
这个答案是针对 C 的,它在 C++ 中是类似的。
该示例实际上与C11 标准 6.4.9p3 中的相同:
#define glue(x,y) x##y
glue(/,/) k(); // syntax error, not comment
Run Code Online (Sandbox Code Playgroud)
您看到的错误:
错误:粘贴“/”和“/”没有给出有效的预处理标记
来自##需要预处理令牌的结果。简而言之,预处理标记是标识符、预处理数字、字符串文字、标点符号等。(另请参阅关于标记化的 gcc 文档)。结果//字符串不是预处理标记,因此##此处的结果不会是预处理标记。在C标准6.10.3.3p3规定,如果结果##“不是一个有效的预处理标记,这种行为是未定义”。在这种情况下,您使用的编译器选择发出错误。它不会以与以下不起作用的方式相同的方式工作:
concatenate(:, b) // error, `:b` is not a preprocessing token
concatenate(%, b) // error, `%b` is not a preprocessing token
// etc.
Run Code Online (Sandbox Code Playgroud)
也许例如从另一边,例如%=是一个有效的标记,一个标点符号。以下是可以的:
concatenate(%, =)
concatenate(/, =)
concatenate(a /, = b)
concatenate(<, :)
Run Code Online (Sandbox Code Playgroud)
无论如何,即使//是有效的预处理,注释也会在翻译阶段 3 中替换单个空格,而在删除注释后,在翻译阶段 4 中执行预处理器,请参阅C11 翻译阶段。因此,即使它会导致//令牌,它也是无效的,因为它在 C 中没有任何意义(注释除外)。