i = ++i和++i之间的区别

8

2
重复的问题?http://stackoverflow.com/questions/2902638/post-and-pre-increment-in-c-closed - rkellerm
6个回答

10

i = ++i; 会引发未定义行为,而 ++i; 则不会。

C++03 [5/4节]规定在前后两个序列点之间,标量对象的存储值至多被一个表达式修改一次

i = ++i 中,i 在没有任何中间序列点的情况下进行了两次修改(预增和赋值),因此该行为在C和C++中都是未定义的。

然而,在 C++0x 中,i = ++i 是有定义的 :)。


5
优先级与评估顺序无关。 i = ++i 引发未定义行为,因为在两个序列点之间多次修改了 i - Prasoon Saurav
2
@DumbCoder: 不,如果标准指定某些行为为未定义行为,并且编译器执行您认为合理的操作,则这不是一个“惊喜”。未定义行为意味着编译器可以做任何事情。即使它执行您期望的操作,它仍然严格遵循标准。 - Steve Jessop
2
@DumbCoder:为什么有人要测试和预测已经被标准定义为“未定义”的行为呢?这肯定意味着你不理解“未定义行为”是什么意思,对吧? - Prasoon Saurav
3
@Dumbcoder:我已经阅读并理解了@jalf和@steve在他们的评论中所说的,但作为一个“愚蠢的编码者”,你似乎不想/不愿意理解我所说的话。 - Prasoon Saurav
3
如果我们谈论未定义行为(UB),那么“为什么编译器会执行它的行为?”这个问题是毫无意义的。 - Oliver Charlesworth
显示剩余36条评论

7
写下 i = ++i; 会使变量 i 被写入两次(一次是加一操作,一次是赋值操作),而这两个操作之间缺少一个序列点。根据 C 语言标准规定,这意味着它引起了未定义的行为。
这意味着编译器可以自由地将 i = ++i 实现为与 i = i + 1 相同,或者实现为 i = i + 2(在某些与流水线和缓存相关的情况下,这实际上是有意义的),或者实现为 format C:\(虽然荒谬,但在技术上被允许)。

+1 对于提到序列点,这是非常有用的,需要注意! - Paul Dixon
请参考此处关于序列点的描述。 - LarsH

3

i = ++i

经常会但不一定会给出结果

i = i;


i +1;


即得 i = 10


正如评论所指出的那样,这是未定义的行为,不能依赖此方式


而 ++i 总是会给出


i = i+1;


即得 i = 11;


因此这是正确的操作方式


如果您要对我进行负评,那么请至少礼貌地告诉我帖子的问题所在。 - user466784
我没有给你的回答投反对票,但可能是因为你的回答不够准确,说它“通常会,但不一定”得出某个结果。这在官方上是未定义行为,试图猜测你将得到哪种结果的概率可能会给读者错误的印象,即可以依赖于结果。 - jalf
@jalf - 我看不出kskjon的回答有什么问题。它可能没有达到最大精确度,但完全准确,并且回答了OP的问题。kskjon明确表示i=10的结果“不一定会”发生。我不明白这怎么会让读者产生错误的想法,认为可以依赖该结果。 - LarsH
@LarsH:就像我说的,我没有对它进行负面评价,你是对的,他的回答没有事实错误。但是它确实给人一种印象,即您可以“通常”依赖特定的答案。或者具体地说,通过不提到行为实际上完全是未定义的,可能会让读者相信该行为在某种程度上受到限制,您仍然可以依赖它来做一些明智的事情,或者它可能会以一种固定数量的方式行事。如果他编辑它并包括前者是未定义的的说明,我会很高兴。如果我必须猜测,那就是为什么它被投票否决的原因。 - jalf

2
如果i是标量类型,那么i = ++i是未定义的行为,++i等同于i+=1。 如果i是类类型并且该类中有重载的operator++,那么i = ++i等同于i.operator=(operator++(i)),这不是未定义的行为,并且++i只执行++ operator,具有任何您放置在其中的语义。

1
第一个的结果未定义。

只有当++是内置的++运算符时,才是如此。如果它被重载了,那么它就不是未定义行为。 - Armen Tsirunyan
@Armen:这正是我要在Prasoon的回答中说的,但我注意到提问者说“i”是一个“整数”。我认为可以合理地假设这意味着一个整数类型,因此会导致未定义行为。 - Steve Jessop

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接