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不是非常精通,只能看出大概,希望精通人员补充一下:)