这是CSharp(C#)的 bug还是新特性?论一道编程题。

 

 7.设int x=6;,执行语句X+=X-=X*X;后,x的值是(      )
 A.-60   B.0
 C.6      D.36

请问答案是什么?

依据:2010年10月自考高级语言程序设计(一)参考答案

这一题答案是:A

说来白痴,本人秒答,结果瞬错。唉……再简单的题目,不认真也是个错。反省……

 

于是发扬认真求知者精神,写代码研究。

哇!吓人!控制台输出 -24 。这是什么第5选项吗。

将语句拆分,逐段输出。

            int X = 6;

            X = 6;
            X=(X * X);
            Console.WriteLine("X = 6,,,X * X: \t\t" + X.ToString()); //输出 36
            
            X = 6;
            X -= X * X;
            Console.WriteLine("X = 6,,,X -= X * X: \t\t" + X.ToString());//输出 -30,显然 -= 可以正常使用

            X = 6;
            X += X -= X * X;
            Console.WriteLine("X = 6,,,X += X -= X * X: \t\t" + X.ToString());//输出 -24,到这就完全歪了。
            X = -30;
            X += X;
            Console.WriteLine("X = -24,,,X += X: \t\t" + X.ToString());//输出 -60,显然 += 可以正常使用

 

显然代码没有错误。那么为什么不是 -60,而是 -24呢?

考虑到 实验代码是C#,估计C# 对的执行的机制可能比较特别。

再写C++win32 版实验,输出正确为:-60

	int X =6;
	X+=X-=X*X;

	
	printf("%d",X);

	getchar();

写C++CLR 版实验,输出正确为:-60

	int x =6;
	x +=x-=x*x;
	Console::WriteLine(x.ToString ());
	Console::ReadLine();

那么确认是C#的机制作祟。

 

一般公式X += X -= X * X可以写这样的等效过程。

int temp =X*X;
X-=temp;// x=x-temp 执行前X为 6,x=6-36=-30,
temp =X;
X+=temp;//x=x+temp 执行前X为-30,x=-30+(-30)=-60


而 C#的等效过程。可能是这样了。

int temp=X*X;
temp =X-temp;//执行前X为 6,6-36=-30 
X+=temp;//x=x+temp 此时执行前的X仍然为 6,x=6+(-30)=-24

其中"-=" 不执行对 X 的赋值,“-=”居然变成了别的东西。这岂不是我们学的语法知识失效了?!还是说我孤陋寡闻不知道C#有关于"-="的附加说明。

想问:这是CSharp(C#)的 bug还是新特性?

 

---------


 将问题发布的msdn论坛后得到一些解答:

    Visual Studio 开发人员中心 > Visual Studio 论坛 > Visual C# > 这是CSharp(C#)的 bug还是新特性?

 

---截取msdn上热心网友的回复:

在C#中,如果类似自增等表达式重叠(包含变量自身),变量会被自动压入堆栈保存内容,直至最终结果:

x+=x-=x*x,展开为:

x=x+x-x*x:x=6+6-6*6=>6+6-36=>6-30=-24

我用反编译Reflector查看IL代码:

     .entrypoint
        .maxstack 4
        .locals init (
            [0] int32 x)
        L_0000: nop
        L_0001: ldc.i4.6
        L_0002: stloc.0
        L_0003: ldloc.0  
        L_0004: ldloc.0
        L_0005: ldloc.0
        L_0006: ldloc.0
        L_0007: mul      6*6=36
        L_0008: sub      6-36=-30
        L_0009: dup     
        L_000a: stloc.0
        L_000b: add    -30+6=-24
        L_000c: stloc.0
        L_000d: ldloc.0
        L_000e: call void [mscorlib]System.Console::WriteLine(int32)
        L_0013: nop
        L_0014: ret
我对IL不是非常精通,只能看出大概,希望精通人员补充一下:)


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值