为什么会发生以下错误?
#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;
}
我认为concatenate(/, /)
会告诉预处理器用//
替换它,然后当它进一步分析时,整行将被解释为注释。
这个案子到底发生了什么?
发布于 2020-01-12 13:30:09
这个答案适用于C,在C++中类似。
该示例与C11标准6.4.9p3中的示例完全相同。
#define glue(x,y) x##y
glue(/,/) k(); // syntax error, not comment
您所看到的错误:
错误:粘贴"/“和"/”不能提供有效的预处理令牌
因此,##
的结果需要预处理令牌。简而言之,预处理令牌是标识符、预处理数字、字符串文本、标点符号等等。(另见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.
例如,可能来自另一边,例如%=
是一个有效标记,标点符号。以下各点可以:
concatenate(%, =)
concatenate(/, =)
concatenate(a /, = b)
concatenate(<, :)
无论如何,即使//
是有效的预处理,在翻译阶段3中,注释被替换为单个空格,而预处理程序在删除注释后在翻译阶段4中执行,请参见C11翻译阶段。因此,即使它会导致//
令牌,它也将是无效的,因为它在C中并不意味着任何东西(除了注释)。
发布于 2020-01-12 13:23:13
对于C++:
##
必须产生有效的预处理令牌。
//
不被视为预处理令牌。相反,包括//
介绍器在内的评论被认为是空白,参见C++17标准的[lex.token]/1 (最终草案)。
如果##
不生成有效的预处理令牌(如此处),则程序具有未定义的行为。见[cpp.concat]/3。这意味着编译器甚至不需要用错误消息告诉您您搞砸了。
在执行宏定义和替换等预处理器指令之前,所有注释都会从源文件中删除,因此即使您可以生成//
令牌,它也不会被替换,而是语法错误。请参阅[lex.phases]/1.3-1.4
https://stackoverflow.com/questions/59704111
复制相似问题