近日在看书时偶尔遇到了一个自增,自减运算符的问题,在C#中和C中同一个表达式得到的结果却不一样,自己实在想不明白,特来请教,谢谢各位!
问题是这样的:
设int a=10;
计算a+=a-=a的值。
在Turbo C中得到的结果是0;而在C#中(Visual Studio 2005环境)得到结果确实10!为什么啊?我觉得应该是0啊,因为-=,+=这两个运算符都是右结合性,所以先计算a=a-a=10-10=0,a=a+a=0!另:我比较穷,所以分数较少,见谅!

解决方案 »

  1.   

    机制不一样的
    .NET下,当运行完a-=a时候,前面的a+=a的第一个a依然是10
    可以理解成这样
    a+=a-=a
    int a1,a2,a3
    a1=a2=a3=10;
    a1+a2-a3;
      

  2.   

    a+=a-=a
     有意思。
    我看这个是编译的问题:
    C 的编译是从右向左进行编译的  a-=a(0) , a+=a(0)
    C#则相反 a+=a(20) , a-=a(10)
      

  3.   

    to:bo111,应该不是这个原因,因为C#的书上明确表明自增,自减运算符的结合方向是右结合性!
      

  4.   

    有意思~
    刚才用ILDasm看了下就明白了:.method private hidebysig static void Main() cil managed
    {
        .entrypoint
        .maxstack 3
        .locals init (
            [0] int32 a)
        L_0000: nop 
        L_0001: ldc.i4.s 10
        L_0003: stloc.0 //a=10;
        L_0004: ldloc.0 //第一个a入运算栈
        L_0005: ldloc.0 //第一个a入运算栈
        L_0006: ldloc.0 //第一个a入运算栈
        L_0007: sub //10-10
        L_0008: dup //将结果复制
        L_0009: stloc.0 //将结果保存回a,至此a-=a运算结束.注意栈上现在用于运算的就是原先a的值10和a-=a的值0了
        L_000a: add //10+0
        L_000b: stloc.0 //将结果10保存回变量a
        //以下是在控制台输出a的值~
        L_000c: ldloc.0 
        L_000d: call void [mscorlib]System.Console::Write(int32)
        L_0012: nop 
        L_0013: ret 
    }
    对应的C#源码:
    using System;class test
    {
    static void Main ()
    {
    int a = 10;
    a+=a-=a;
    Console.Write (a);
    }
    }
     
      

  5.   

    晕...没贴好,重贴~
    .method private hidebysig static void Main() cil managed
    {
        .entrypoint
        .maxstack 3
        .locals init (
            [0] int32 a)
        L_0000: nop 
        L_0001: ldc.i4.s 10
        L_0003: stloc.0 //a=10;
        L_0004: ldloc.0 //第一个a入运算栈
        L_0005: ldloc.0 //第二个a入运算栈
        L_0006: ldloc.0 //第三个a入运算栈
        L_0007: sub //10-10
        L_0008: dup //将结果复制
        L_0009: stloc.0 //将结果保存回a,至此a-=a运算结束.注意栈上现在用于运算的就是原先a的值10和a-=a的值0了
        L_000a: add //10+0
        L_000b: stloc.0 //将结果10保存回变量a
        //以下是在控制台输出a的值~
        L_000c: ldloc.0 
        L_000d: call void [mscorlib]System.Console::Write(int32)
        L_0012: nop 
        L_0013: ret 
    }
      

  6.   

    导致这个结果的原因就是编译器在生成IL的时候
    是先将三个a的值入栈了~
      

  7.   

    还是楼上讲的彻底!!Thank U!!
      

  8.   

    int a = 10;a += a -= a;在C#中运行结果:a = 10; 这里的a在内存中依然是10而把它们分开来写`` a += a;a -= a;结果就为0
      

  9.   

    <font color=red>...</font>
      

  10.   

    Turbo C 中不也是先将3个a入栈吗
      

  11.   

    简直就是瞎说,赋值运算符当然是右结合,C#也不例外。
    这是C#的一个老问题了,C#其实是想规范一些行为,所以特别做出了这样的规定。对于 A operator B operator C这样的式子。
    从左至右依次计算A、B、C的值,然后根据operator的结合顺序计算最终结果。
    这一点,你可以在C#语言规范中找到。