int i = 0;
i = i++;
MessageBox.Show(i.ToString());结果i是0。这是为什么?
JAVA和C#中的计算结果都是i==0,而在C++中i==1。
待高手解。

解决方案 »

  1.   

    现在我坚持认为这是C#和Java编译器的bug,嗯
      

  2.   

    这是 编译器 的规则问题,C# 和 JAVA 的编译器 是区分 左增 和 右增的int i = 0;
    i = i++;
    MessageBox.Show(i.ToString());
    -------------------
    int i = 0;
    i = ++i;
    MessageBox.Show(i.ToString());
      

  3.   

    这和语言的编译机制有关,可参考编译原理
    说明C++的编译是执行完整个行后对++进行运算的,故在显示时为1
    1、执行i++表达式的到返回值0
    2、执行i=表达式(付值),i=0
    3、执行++,i=1
    而C#和JAVA是以表达式为单位进行编译的,即先
    1、执行i++表达式的到返回值0
    2、执行++,i=1
    3、执行i=表达式(付值),i=0
    这是个人的理解,我认为差别就在此,在这些语言的编译器和优先级里,建议尽量避免此类问题,宁可多写几句:)
      

  4.   

    这样的结果是对的!i++是一个表达式,把这个表达式的值赋值给了i,i++这个表达式的值是i的原值0!所以输出结果是0!c语言中就学过,表达式的值和变量的值是不一样的!
      

  5.   

    To:alexzhang00(三角猫) 
    C++的编译器 也是区分 左增 和 右增的啊
      

  6.   

    zhpsam109(孤寂无边) :
    你的说法我认同,但是,C++为什么不同?
      

  7.   

    和C/C++精神相违背的C语系语言的编译器,就是有bug的编译器
    按照C/C++的规则,i++总是执行完当前规则后在给i加一
    故等效于i = i;i += 1;不晓得实现C#编译器的时候咋想的
      

  8.   

    要知道开发C#的那个人叫以前在Borland做Delphi和JBuilder的,估计是习惯了那些思路吧,坚决拥护C++
      

  9.   

    其实这个问题表面上很容易理解,但还有个更“鬼”的意义,就是:
    ++ 要比 = 更优先
    那为什么还是0 呢?我们从IL 来分析:  IL_0000:  ldc.i4.0 //把0压入evaluation stack
      IL_0001:  stloc.0 //取自evaluation stack顶部一个值回填到变量(已经完成i=i)
      IL_0002:  ldloc.0 //加载
      IL_0003:  dup //拷贝复本到evaluation stack
      IL_0004:  ldc.i4.1 //压入1
      IL_0005:  add //相加
      IL_0006:  stloc.0 //取值(返回值)
      IL_0007:  stloc.0
      IL_0008:  ldloc.0这个小问题过去我曾经碰到过,我个人感觉不可理解,很明显.net(包括vc.net也一样的结果) 和java 一样没有严格按照U先级计算。。(C# 相关文档注明了++ 是计算符里最U先的),而C 是先加后付值的,所以个人感觉是为了兼容java 的步进运行机制
      

  10.   

    我认为正因为 ++ 要比 = 优先执行,所以才应该是0。
    先++,然后将(i++)的值赋给i,于是冲掉了开始的++操作。
    但C++却又不是这个思路。先赋值,后++。
      

  11.   

    ++比=优先也不说明问题,关键是,++返回多少?或者说:int i = 0, j=0;
    j = i++;i肯定是1了,j是多少?
      

  12.   

    int i = 0;
    i = i++;如果是i = ++i;
    就不是零了啊...
    是先赋值在加...
      

  13.   

    这个其实不是错误。对于C++而言,它对于后置自增运算符的解释是,在语句执行完毕后自增。所以,C++先执行i=i,最后再自增i,得到结果1。
    对于C#而言,它对于后置自增运算符的解释是,在得到变量结果后自增。所以,C#先得到i++的结果,然后马上自增,再进行i=i,但由于这个时候,后面的i的结果已经被获取,为0,C#并不会对其进行第二次获取值,所以i最终的结果是0。
    而C#为什么不采取与C++同样的处理方式呢?原因应该非常简单,因为C#是编译成IL的,在IL中,并没有针对自增和自减所特别优化的指令。而C++是编译成汇编语言,发明自增和自减运算符其目的就在于优化汇编代码,使用自增的指令代替两数相加的指令可以大大的提高效率。所以,在C#中,自增和自减运算符会被编译器解释成i = i + 1或者i = i + 1这样的代码。而后置的自增/自减运算符处理方式则只是简单的将i的值暂存,等到自增/自减结束后返回暂存的值。这样也简化了重载自增/自减运算符的代码,不准分前置和后置重载,后置的处理方式相对于前置总是固定的。
      

  14.   

    这个问题我的理解是这样的,i=i++在C#和JAVA中背后是分成这样的过程的:++优先级高,所以先执行i++
    i++要分成两步来执行:
    i=i+0,这里很关键:
    i+0贮存在一个临时变量中:
    i+0---->temp此时temp=0+0=0;
    然后i执行i=i+1,此时i=1
    然后再执行赋值运算i=temp
    所以还是等于0在c++中操作就不是一样的了,在c++中:
    i++是通过累加寄存器来操作,他不会通过中间临时变量,然后直接返回值.
    所以C++运行效率很高.为什么JAVA和C#要这样设计呢?是因为便于装箱,在装箱的时候更有效率.比如:
    object oj=(object)(i++)这种形式的运算,此时直接把temp的地址返给oj就是了,那么i怎么办?i然后自己执行自己的++运算,如果i不再使用,直接拉圾回收。大家可以通过以下的代码来验证:
    object o=(object)(i++);
    this.label1.Text=o.ToString();//输出为0
    this.label2.Text=i.ToString();//输出为1
    但是上面的过程是不是我说的那样,得通过IL来验证。不知我理解得正确不?望MS的专家们来讲解一下.
      

  15.   

    上面的有误,由于i++是后置运算,在c#和java中,上面的i=i+0这个过程不必要的,应该是将i的值直接赋给中间变量temp
      

  16.   

    我的理解:C#、JAVA中i是一个Integer的对象,被i++重新附值为0;C++中i是一个值变量,放在内存中,i++后加所以在附值后再加。
      

  17.   

    无错了,C++是效率至上的,所以自增和自减运算符会优化汇编代码。而且系统内定的后置的自增/自减运算符不会像C#一样先返回值然后再自增或自减,因为这样必然会生成变量的一个拷贝,从而影响性能,所以C++的后置自增/自减运算符规定在语句执行完后再执行。换言之,C#为了简单,把后置的自增运算符定义为:operator++ ( int i, int postfix )//注:仿照C++的规则,利用伪参数postfix来表明是后置
    {
      int _i = i;
      ++i;
      return _i;
    }而我们在C++中重载后置自增/自减运算符时也采取类似的方法。
    但对于C++编译器而言,这种方案要创建一个临时的变量_i,还需要进行两次赋值,对于效率至上的C++是不可接受的。所以C++采取了不同于C#的复杂的方式。
      

  18.   

    越说越出轨了,不是什么编译器BUG之类的,注意这个:The operand of a postfix increment or decrement operation must be an expression classified as a variable, a property access, or an indexer access. The result of the operation is a value of the same type as the operand.注意最后一句:result of the operation is a value of the same type as the operand.
    在MS的C# 语言规范的7.5.9 已经说明了,i++ 将返回i的原值然后再去瞧瞧VC的解释,msdn 2003的
    ms-help://MS.MSDNQTR.2003FEB.2052/dv_vccelng4/html/ellrfcplsplspostfixincrementanddecrementoperators.htmmsdn2005的:
    ms-help://MS.VSCC.2003/MS.MSDNQTR.2005APR.1033/vclang/html/_pluslang_C.2b2b_.Postfix_Increment_and_Decrement_Operators.htm或者自己再写各写一个程序,去反汇编回来瞧瞧就知道了我想楼主只是奇怪MS的动机
      

  19.   

    alexzhang00(三角猫) 的答案是正解;这是C#的语法规定的,如果你连“左增 和 右增”的语法都没搞清楚的话,只能说语法不清楚;说编译器有问题的需要在语法上下点功夫;
      

  20.   

    alexzhang00(三角猫) 的答案是正解;这是C#的语法规定的,如果你连“左增 和 右增”的语法都没搞清楚的话,只能说语法不清楚;说编译器有问题的需要在语法上下点功夫;
    晕。C语系的都区分前置和后置的自增自减运算符。。现在在这里讨论的是对于后置自增自减运算符C++和C#处理方式的不同,C++的处理方式复杂,C#的处理方式简单,但都不是Bug,因为在他们各自的文档中是写的很清楚的。真正正确的解释应该是 tajlolo(tajlolo) 的分析。
      

  21.   

    这样的结果是对的!i++是一个表达式,把这个表达式的值赋值给了i,i++这个表达式的值是i的原值0!所以输出结果是0!c语言中就学过,表达式的值和变量的值是不一样的!