为什么我= ++我调用未定义的行为?
这个问题在这里已经有了答案:
你错过了一些未定义的行为。 未定义的行为只是意味着编译器可以做任何想做的事情。 它可以抛出一个错误,它可以(如GCC所示)显示一个警告,它可以导致恶魔飞出你的鼻子。 最主要的是,它不会表现良好,编译器之间的行为也不一致,所以不要这样做!
在这种情况下,编译器不必在返回语句的rhs之前让操作符的lhs的副作用完成。 这对你来说似乎很有趣,但你不会像电脑那样思考。 如果需要,它可以计算返回值并将其返回到寄存器中,将其分配给i,然后对实际值执行增量。 所以它看起来更像
register=i+1;
i=register;
i=i+1;
该标准不能保证这不会发生,所以不要这样做!
未定义的行为出现是因为变量i
在两个序列点之间不止一次被修改。 序列点是之前的评估的所有副作用都可见的点,但未见副作用。 该标准规定:
在前一个和下一个序列点之间,一个对象应该通过评估一个表达式最多修改其存储值一次。 此外,先验值只能读取以确定要存储的值。
那么,我们担心的副作用是什么?
++i
,它给i赋值i+1
i = ++i
,它给我i表达式++i
的值,即i+1
所以,我们会得到两个(不可否认的,等价的)副作用:将i+1
分配给变量i
。 我们关心的是,在这两个序列点之间会发生这些副作用?
什么操作构成序列点? 有多个,但这里只有一个实际相关:
i = ++i
是一个完整的表达式) 即,预增量++i
不是序列点 。 这意味着两个副作用(增量和分配)将发生在相同的两个序列点之间,修改相同的变量i
。 因此,这是不确定的行为; 两个修改碰巧具有相同的值的事实是无关紧要的。
但为什么在序列点之间多次修改一个变量是不好的? 为了防止这样的事情:
i = ++i + 1;
这里, i
是递增的,但是由于预增量的语义,它也被分配了值(i+1) + 1
。 由于副作用具有模糊的顺序,因此行为未定义。
现在,假设在标准中有一个特殊情况,只要值相同,两个序列点之间的多个修改就可以,但这可能会使编译器实现无用地复杂化,而没有太多好处。
链接地址: http://www.djcxy.com/p/73275.html上一篇: Why does i = ++i invoke undefined behaviour?
下一篇: sequence points in c