This exact example is covered in the
draft C99 standard(
same details in C11) section
6.4 Lexical elements paragraph 4 which in says:
If the input stream has been parsed into preprocessing tokens up to a
given character, the next preprocessing token is the longest sequence
of characters that could constitute a preprocessing token. [...]
which is also known as the
maximal munch rule which is used in in lexical analysis to avoid ambiguities and works by taking as many elements as it can to form a valid token.
the paragraph also has two examples the second one is an exact match for you question and is as follows:
例子2:程序片段x+++++y被解析为x ++ ++ + y,这违反了增量运算符的约束条件,即使解析成x ++ + ++ y可能会产生正确的表达式。这告诉我们:
a+++++b
将被解析为:
a ++ ++ + b
这违反了对后置自增的限制,因为第一个后置自增的结果是一个rvalue,而后置自增需要一个lvalue。这在第
6.5.2.4
节
后缀递增和递减运算符中有所涵盖,其中写道(
重点标记为mine):
后缀递增或递减运算符的操作数应具有限定或未限定的实际或指针类型,并且必须是可修改的lvalue。
和
后缀++运算符的结果是操作数的值。
这本书
C++ Gotchas 也在
Gotcha #17
中涵盖了这种情况
最大匹配问题,在
C++中也是同样的问题,并且它还提供了一些示例。它解释说,在处理以下字符集时:
->*
词法分析器可以执行以下三种操作之一:
- 将其视为三个标记:
-
、>
和 *
- 将其视为两个标记:
->
和 *
- 将其视为一个标记:
->*
最大匹配规则可避免这些歧义。作者指出,在C++上下文中,它:
解决的问题比引起的问题还要多,但在两种常见情况下,它是一种烦恼。
第一个例子是模板,其模板参数也是模板(在C++11中已解决),例如:
list<vector<string>> lovos
^^
这将尖括号解释为移位运算符,因此需要一个空格来消除歧义:
list< vector<string> > lovos
^
第二种情况涉及指针的默认参数,例如:
void process( const char *= 0 ); // error!
^^
如果不命名参数,则*=
会被解释为赋值运算符,解决方案是在声明时为参数命名。
x+++++y
被解析为x ++ ++ + y
,这违反了增量运算符的约束条件,尽管解析x ++ + ++ y
可能会产生正确的表达式。” - Jonathan Leffler