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
。由于第一个后置增量产生一个右值,第二个后置增量无法应用于它,编译器将给出一个错误

w,在C++中,您可以超载<代码>运算符++>代码>以产生一个LValk,允许它工作。例如:

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!
                         ^^