C 为什么';t a+++++;b工作?
此代码给出以下错误: 错误:增量操作数需要左值 但是如果我在C 为什么';t a+++++;b工作?,c,lvalue,C,Lvalue,此代码给出以下错误: 错误:增量操作数需要左值 但是如果我在a++和+++b中都加上空格,那么它就可以正常工作了 int main () { int a = 5,b = 2; printf("%d",a+++++b); return 0; } 第一个例子中的错误是什么意思 int main () { int a = 5,b = 2; printf("%d",a++ + ++b); return 0; } ++返回上一个值,即右值。你不能增加它。你的编译器拼
a++
和+++b
中都加上空格,那么它就可以正常工作了
int main ()
{
int a = 5,b = 2;
printf("%d",a+++++b);
return 0;
}
第一个例子中的错误是什么意思
int main ()
{
int a = 5,b = 2;
printf("%d",a++ + ++b);
return 0;
}
++返回上一个值,即右值。你不能增加它。你的编译器拼命地试图解析
a+++b
,并将其解释为(a+++++++b
)。现在,后增量(a++
)的结果不是,即不能再次后增量
请不要在产品质量程序中编写此类代码。想想那个跟在你后面的可怜虫,他需要解释你的代码。printf(“%d”,a+b)根据最大芒克规则,代码>被解释为(a+++++++b
++
(后缀)的计算结果不是左值
,但它要求其操作数是左值
!!
6.4/4说
下一个预处理标记是可构成预处理标记的最长字符序列“
因为它会导致未定义的行为
是哪一个
(a++)++ +b
是的,你和编译器都不知道。
编辑:
真正的原因正如其他人所说:
它被解释为(a+++++++b
但是post increment需要一个左值(这是一个带有名称的变量),但是(a++)返回一个不能递增的右值,从而导致您收到错误消息
Thx向其他人指出这一点。编译器是分阶段编写的。第一阶段称为lexer,将字符转换为符号结构。因此“++“变成类似于枚举符号\u PLUSPLUS
。稍后,解析器阶段将其转换为抽象语法树,但不能更改符号。您可以通过插入空格(除非引号中有结束符号)来影响lexer
普通的lexer是贪婪的(有一些例外),因此您的代码被解释为
c = (a++)++ + b
c = (a) + ++(++b)
c = (a++) + (++b)
解析器的输入是一个符号流,因此您的代码类似于:
a++ ++ +b
解析器认为语法上不正确的。(基于注释进行编辑:语义不正确,因为不能将++应用于r值,而a++会导致该值)
是
没关系。您的其他示例也是如此。我认为编译器将其视为
c=((a++++)++b)
++
必须具有可修改的值作为操作数。a是一个可以修改的值<代码>a++
但是它是一个“右值”,不能修改
顺便说一下,我在GCC C上看到的错误是相同的,但措辞不同:
levalue required as increment operand
lexer使用通常称为“maximum munch”的算法来创建令牌。这意味着,当它在读取中的字符时,它会不断地读取字符,直到它遇到一些不能作为它已经拥有的相同标记的一部分的东西(例如,如果它一直在读取数字,那么它拥有的是一个数字,如果它遇到一个a
,它知道这不能是数字的一部分。因此它停止并将a
留在输入缓冲区中,作为下一个标记的开始)。然后它将该标记返回给解析器
在本例中,这意味着++++
将变为a+++++++b
。由于第一个后置增量产生一个右值,第二个后置增量无法应用于它,编译器将给出一个错误
a++ +b
->*
list< vector<string> > lovos;
^
编译和运行(尽管它不做任何事情),我有HANY(VC++,G++,科莫).< /P> < P>这个确切的例子包含在(C11)部分的相同细节中,在上面说:
如果输入流已被解析为预处理令牌,则 给定字符,下一个预处理标记是最长的序列 可构成预处理标记的字符的数目。[…] 它也被称为,用于词汇分析,以避免歧义,并通过尽可能多的元素来形成有效的标记 本段还有两个示例,第二个示例与您的问题完全匹配,如下所示: 示例2程序片段x+++y被解析为x+++++y,这 违反增量运算符上的约束,即使parse x +++++y可能会生成正确的表达式 这告诉我们:struct bad_code {
bad_code &operator++(int) {
return *this;
}
int operator+(bad_code const &other) {
return 1;
}
};
int main() {
bad_code a, b;
int c = a+++++b;
return 0;
}
将被解析为:
a+++++b
这违反了后期增量的约束,因为第一次后期增量的结果是右值,后期增量需要左值。这在第6.5.2.4节Postfix increment and decreation操作符中有介绍,该操作符表示(重点):
后缀递增或递减运算符的操作数应具有
合格或不合格实数或指针类型和应为
可修改的左值。
及
后缀++运算符的结果是操作数的值
< C++ > GoCHAAS也涵盖了这个例子,在代码< >查查17 中,C++中也是同样的问题,并且给出了一些例子。它解释了当处理下面的字符集:
a ++ ++ + b
词法分析器可以执行以下三项操作之一:
- 将其视为三个令牌:
-
、
和*
- 将其视为两个令牌:
->
和*
- 将其视为一个令牌:
->*
最大MunCH规则允许避免这些歧义,作者指出它(在C++上下文中):
解决的问题比它造成的问题多得多,但有两个共同点
在这种情况下,这是一种烦恼
第一个示例是其模板参数也是模板的模板(在C++11中解决),例如:
a++ +b
->*
list< vector<string> > lovos;
^
会
void process( const char *= 0 ); // error!
^^