2011-07-16 79 views
27

可能显示的文件:
Why does this go into an infinite loop?i = i ++不增加i。为什么?

比如像i = i++具有在C和C++未定义的行为,因为标量对象的值是变化的两倍相同的表达内,而不插入序列点。

但是我想这些表达式在C#或Java中有明确定义的行为,因为AFAIK参数的评估是从左到右,并且有全部的序列点。

也就是说,我期望i = i++相当于i++。但事实并非如此。以下程序输出0

using System; 
class Program 
{ 
    static void Main(string[] args) 
    { 
     int i = 0; 
     i = i++; 
     Console.WriteLine(i); 
    } 
} 

你能帮我理解为什么吗?

免责声明: 我充分认识到,无论是否上述结构的行为定义,他们是愚蠢的,无用的,不可读的,不必要的,不应该在代码中使用。我只是好奇。

+6

@Downvoter:留下评论? –

+1

他们通常不会:) – Tigran

+5

这是去年有关Java的问题,但在C#中回答(这两个工作同样适用于这种情况):http://stackoverflow.com/questions/3831341/why-does-this-go- into-an-infinite-loop – BoltClock

回答

38

的行为在C#良好限定和所述评价顺序是:

  1. 左侧i被评估以可变i
  2. 右侧被评估为0,并且i递增(现在i==1
  3. ,则执行分配,它设置i为0。(现在i==0

最终结果为i==0

一般来说,你首先创建一个表达式树。为了评估它,您首先评估左侧,然后评估右侧,最后评估根部的操作。以递归方式进行。

+0

啊!这说得通。我很傻:) –

+3

在Java中,如果你让'i'变得不稳定(在我的测试中,通常在1亿次迭代中测试65次),你可以偶尔从并行线程观察值'1'。 – starblue

+1

我= ++我应该工作得很好。 – arkoak

17

后增量表达式i++的结果是i的原始值。因此在i++已经评估(递增i)后,您将旧值i分配给... i

只需使用

i++; 

;)

+1

我意识到预增量和后增量。我很困惑,因为我期望增量的副作用发生在整个表达式的评估之后......很明显我错了 –

+0

@阿门是啊,c#几乎是从左到右 –

+3

@Marc我找到了公式表达式是从左到右混淆的。我更喜欢把表达式看作是一棵树,然后递归地评估它。每个节点首先从左到右评估它的参数并最终执行它自己。 – CodesInChaos

3

好了,右边的表达必须在分配之前可以进行评估。现在,i++将评估当前价值i,我的价值将随后增加1。但是,这项任务尚未执行,如果是,则会覆盖当前值i(1),无论rhs表达式评估的值是多少,您的情况为0.

关键的区别是之间++i(预增量,这之后递增评估为的i值)和i++,或后递增,其评估对的i的电流值之前递增

假如你使用++i代替,右手边的表达会评估为1,导致我== 1

15

i = ++i是代码,做你认为什么是怎么回事。 i++实际上表现有点不同。

随着i++i值增加,但i++值不是i新的价值,这是以前的值。所以当你做i = i++时,你会说“增加i的值,然后将i设置为旧值”。

+5

重新第一行;只是'我++;'会是他正在寻找的代码 –

+3

我不认为他正在寻找任何代码,但他正在寻找更好的理解C#语言。特别是发生哪种次序副作用以及表达式中多个赋值结果如何表现同一变量。 – CodesInChaos

+1

@Marc:除了我不寻找任何代码:) –

相关问题