"x = ++x"它真的是未定义的吗?
我在项目上使用 Coverity Prevent 来查找错误。
它报告此表达式的错误(变量名称当然已更改):
x=
(a>= b) ?
++x: 0;
消息是:
EVALUATION_ORDER 缺陷:在“
x=(a>= b) ? ++x: 0;
”中,“x
”被写入“x”
”(赋值 LHS)并写成“(a>= b) ? ++x: 0;
”,但副作用发生的顺序是未定义的,因为有没有中间序列点。消息结束
虽然我可以理解“x = x++
”是未定义的,但这对我来说有点困难。这是误报吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
条件运算符
?:
在条件(第一个操作数)的求值和第二个或第三个操作数的求值之间有一个序列点,但在求值之后没有专用的序列点第二个或第三个操作数。这意味着此示例中x
的两个修改可能会发生冲突(不是由序列点分隔)。所以,Coverity Prevent 是正确的。您在这方面的陈述实际上
与
x = ++x
中的问题相同。现在,您的问题的标题似乎表明您不知道
x = ++x
是否未定义。它确实是未定义的。它未定义的原因与x = x++
未定义的原因相同。简而言之,如果同一对象在一对相邻序列点之间被修改多次,则行为是未定义的。在这种情况下,x
通过赋值和++
进行修改,并且没有序列点来“隔离”这些修改。因此,行为是未定义的。在这方面,++x
和x++
之间完全没有区别。Conditional operator
?:
has a sequence point between evaluation of the condition (first operand) and evaluation of second or third operand, but it has no dedicated sequence point after the evaluation of second or third operand. Which means that two modifications ofx
in this example are potentially conflicting (not separated by a sequence point). So, Coverity Prevent is right.Your statement in that regard is virtually equivalent to
with the same problem as in
x = ++x
.Now, the title of your question seems to suggest that you don't know whether
x = ++x
is undefined. It is indeed undefined. It is undefined for the very same reasonx = x++
is undefined. In short, if the same object is modified more than once between a pair of adjacent sequence points, the behavior is undefined. In this casex
is modified by assignment and by++
an there's no sequence point to "isolate" these modifications from each other. So, the behavior is undefined. There's absolutely no difference between++x
andx++
in this regard.无论消息的准确性如何,用
x= (a>= b) 替换有问题的代码? x+1: 0;
达到了相同的目的,没有任何混乱。如果该工具感到困惑,那么也许下一个查看此代码的人也会感到困惑。这确实假设
x
没有您在此依赖的具有副作用的重载增量运算符。Regardless of the accuracy of the message, replacing the code in question by
x= (a>= b) ? x+1: 0;
achieves the same end without any confusion. If the tool is confused then maybe the next person to look at this code will be too.This does assume that
x
does not have an overloaded increment operator with side-effects that you rely on here.语句
x = ++x;
在命中 x 写入两次rel="nofollow noreferrer">序列点,因此行为未定义。The statement
x = ++x;
writes to the variablex
twice before hitting the sequence point and hence the behavior is undefined.很难想象编译器会生成“x = ++x;”的代码。事实上,它与“++x”的工作方式不同。然而,如果 x 不是易失性的,则编译器处理语句“y = ++x;”是合法的。 as
语句“x = ++x;” 如果将
一个算术赋值表达式的目标太快地用作另一个算术赋值表达式的源操作数会导致管道延迟,则前一种优化可能是合理的。如果递增的变量和分配的变量相同,显然是灾难性的。
如果变量“x”是易失性的,我想不出任何代码序列,其中不是故意试图变得刻薄的编译器可以合法地认为“x = x++;”除了读取 'x' 的所有部分一次并将相同的正确值写入 'x' 的所有部分两次之外,具有任何效果。
It is hard to imagine a compiler producing code for "x = ++x;" which would in fact not work the same as "++x". If x is not volatile, however, it would be legal for a compiler to process the statement "y = ++x;" as
The statement "x = ++x;" would thus become
If having the destination of one an arithmetic assignment expression get used too quickly as a source operand for another would cause a pipeline delay, the former optimization might be reasonable. Obviously disastrous if the incremented and assigned variable are one and the same.
If variable 'x' is volatile, I can't think of any code sequence where a compiler that wasn't deliberately trying to be mean could legitimately regard "x = x++;" as having any effect other than reading all parts of 'x' exactly once and writing the same correct value to all parts of 'x' exactly twice.
我认为从逻辑上讲,如果你写“x=++x”或“x=x++”,无论哪种方式,你都会期望最终结果是 x 比开始时多 1。但让它稍微复杂一点。如果你写“x=x+(++x)”怎么办?这与“x=x+(x+1)”相同吗?或者我们先加一,然后将 x 加到它本身,即“x=(x+1)+(x+1)”?如果我们写“x=(x--)+(x++)”怎么办?
即使您可以编写一个语言规范,为这些结构赋予明确的含义,然后可以干净地实现它,您为什么要这样做呢?在对同一变量的赋值中放置一元增量是没有意义的,即使我们强制赋予它意义,它也没有提供任何有用的功能。就像,我确信我们可以编写一个编译器,它会采用“x+1=y-1”这样的表达式,并弄清楚这实际上意味着“x=y-2”,但为什么要麻烦呢?没有任何收获。
即使我们编写的编译器可以用“x=x++-++x”做一些可预测的事情,程序员也必须知道并理解这些规则。没有任何明显的好处,它只会无缘无故地增加程序的复杂性。
I suppose that logically, if you write either "x=++x" or "x=x++", either way you would expect the end result to be that x is one more than it started as. But make it just a shade more complicated. What if you wrote "x=x+(++x)" ? Is this the same as "x=x+(x+1)" ? Or do we add one first and then add x to itself, i.e. "x=(x+1)+(x+1)"? What if we wrote "x=(x--)+(x++)" ?
Even if you could write a language spec that gave unambiguous meaning to these sort of constructs, and could then implement it cleanly, why would you want to? Putting a unary increment in an assignment to the same variable just doesn't make sense, and even if we forced sense out of it, it provides no useful functionality. Like, I'm sure we could write a compliler that would take an expression like "x+1=y-1" and figure out that that really means "x=y-2", but why bother? There's no gain.
Even if we wrote compilers that did something predictable with "x=x++-++x", programmers would have to know and understand the rules. Without any obvious benefit, it would just add complexity to programs for no purpose.
为了理解这一点,您需要对序列点有基本的了解。请参阅此链接:http://en.wikipedia.org/wiki/Sequence_point
对于 = 运算符没有序列点,因此不能保证 x 的值在再次分配给 x 之前会被修改。
In order to understand this you need to have a basic understanding of sequence points. See this link: http://en.wikipedia.org/wiki/Sequence_point
For the = operator there is no sequence point, so there is no guarantee that the value of x will be modified before it is again assigned to x.