C++ &引用;x=++;x";它真的没有定义吗?

C++ &引用;x=++;x";它真的没有定义吗?,c++,operator-precedence,coverity-prevent,C++,Operator Precedence,Coverity Prevent,我正在一个项目中使用查找错误 它报告此表达式的错误(当然变量名称已更改): 信息是: 评估顺序缺陷:在“x=(a>=b)++x:0;”中,“x”写在“x”(赋值LHS)中,写在“(a>=b)++x:0;”中,但副作用发生的顺序没有定义,因为没有中间的序列点。消息结束 虽然我可以理解“x=x++”是未定义的,但这个对我来说有点难。这是假阳性还是假阳性?条件运算符?:在条件求值(第一个操作数)和第二个或第三个操作数求值之间有一个序列点,但在第二个或第三个操作数求值之后没有专用序列点。这意味着在本例中

我正在一个项目中使用查找错误

它报告此表达式的错误(当然变量名称已更改):

信息是:

评估顺序缺陷:在“
x=(a>=b)++x:0;
”中,“
x
”写在“
x
”(赋值LHS)中,写在“
(a>=b)++x:0;
”中,但副作用发生的顺序没有定义,因为没有中间的序列点。消息结束


虽然我可以理解“
x=x++
”是未定义的,但这个对我来说有点难。这是假阳性还是假阳性?

条件运算符
?:
在条件求值(第一个操作数)和第二个或第三个操作数求值之间有一个序列点,但在第二个或第三个操作数求值之后没有专用序列点。这意味着在本例中,
x
的两个修改可能相互冲突(没有被序列点分隔)。因此,Coverity Prevent是正确的

你在这方面的发言实际上相当于

a >= b ? x = ++x : x = 0;
x=++x
中的问题相同


现在,您问题的标题似乎表明您不知道
x=++x
是否未定义。它确实是未定义的。它未定义的原因与
x=x++
未定义的原因完全相同。简而言之,如果在一对相邻序列点之间多次修改同一对象,则行为未定义。在这种情况下,
x
通过赋值和
++
修改,没有顺序点将这些修改相互“隔离”。因此,行为是未定义的。在这方面,
++x
x++
之间绝对没有区别。

不管消息的准确性如何,用
x=(a>=b)替换有问题的代码?x+1:0实现了相同的目的,没有任何混淆。如果工具被弄糊涂了,那么下一个看这段代码的人可能也会被弄糊涂


这确实假设
x
没有一个重载的增量运算符,它没有您在此依赖的副作用。

语句
x=++x
在命中之前写入变量
x
两次,因此行为未定义。

很难想象编译器为“x=++x;”生成的代码实际上与“++x”的工作方式不同。但是,如果x不是易失性的,编译器将语句“y=++x;”处理为

y=x+1; x=x+1; 因此,语句“x=++x;”将成为

x=x+1; x=x+1; x=x+1; x=x+1; 如果将一个算术赋值表达式的目标作为另一个操作数的源操作数使用得太快会导致管道延迟,则前一种优化可能是合理的。如果递增变量和赋值变量是同一个,显然是灾难性的


如果变量“x”是易变的,我想不出任何一个代码序列,如果一个编译器不是故意要求平均值,那么它可以合法地将“x=x++;”视为具有任何效果,而不是只读取“x”的所有部分一次,并将相同的正确值写入“x”的所有部分两次,如果您编写“x=++x”或“x=x++”,那么无论哪种方式,您都会期望最终结果是x比开始时多出一个。但让它变得更复杂一点。如果你写了“x=x+(++x)”?这是否与“x=x+(x+1)”相同?或者我们先加一,然后再加上x本身,即“x=(x+1)+(x+1)”?如果我们写“x=(x--)+(x++)”会怎么样

即使您可以编写一个语言规范,为这些类型的构造赋予明确的含义,然后可以干净地实现它,您为什么要这样做呢?在赋值中给同一个变量加一元增量是没有意义的,即使我们强迫它有意义,它也不能提供有用的功能。比如,我相信我们可以写一个类似“x+1=y-1”的表达式的compliler,然后找出它的真正意思是“x=y-2”,但为什么要麻烦呢?没有收获


即使我们编写的编译器可以用“x=x++-+++x”进行预测,程序员也必须知道并理解规则。如果没有任何明显的好处,它只会毫无目的地增加程序的复杂性。

为了理解这一点,您需要对序列点有一个基本的了解。请参阅此链接:


对于=运算符,没有序列点,因此不能保证在再次将x的值分配给x之前会对其进行修改。

出于对其他开发人员的善意,请不要将其称为
x
a
b
@Dominic:这个问题清楚地表明,名字从原来的名字改过来了。@Joachim-ah,错过了,呸!如果它有一个超负荷的增量操作符,并且有你依赖的副作用,那么有人应该被射杀-如果它有一个重载的递增运算符@Steven,那么就不再存在任何未定义行为的问题。增量运算符将在赋值运算符开始之前完全求值。+1:我很惊讶为什么Comeau Online没有给出这种情况下的错误信息,或者简单的“x=x++;”@chubsdad:我不记得Comeau Online曾经遇到过这样的情况。众所周知,GCC在这种情况下会发出警告,但它不会抱怨
?:
情况。这对于JAVA来说也是未定义的吗?因为我在这里看到,投票最多的ans建议它将给出一个定义的输出。你问题的标题令人困惑。您说您理解
x=x++
是未定义的。然而,您的问题标题似乎询问是否定义了
x=++x
。这是否意味着您不理解
x=++x
是未定义的?或者您的问题实际上是关于有条件的
?:
运算符的情况吗?很抱歉造成混淆。我确实理解x= y=x+1; x=x+1; x=x+1; x=x+1;