自增运算符的迷惑~~ 声明一下,我知道对于不同的C编译器,往往会产生一些不同的后果,但是我只想知道在TurboC2.0中的情况,以及在.NET 2.0中的他又是什么情况。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 更正一下,对于第二段代码:~~~~~~~~~~~~int i =3;i = i++;打印i的值;~~~~~~~~~~~~在TurboC2.0中的结果是4,在Dev C++中的结果是3,在VS2005中的结果是3。 @bandylau() 当然了解i++和++i的区别了,但是我这里是“i=i++”,始终都是i 啊,并不是什么“b=a++”或是“c=++a”啊? 可能我对第二段代码还没有解释清楚吧?~~~~~~~~~~~~int i =3;i = i++;打印i的值;~~~~~~~~~~~~我认为是i先赋值给i,然后i再执行++,在内存中,只有一个i,所以这里有一个++的操作,所以就应该是4啊?? 呵呵,我不是很懂IL代码的,我贴出来,谁帮忙讲解一下啊?C#源码using System;using System.Collections.Generic;using System.Text;namespace ConsoleApplication2{ class Program { static void Main(string[] args) { int i = 3; i = -i++; Console.WriteLine(i); } }}IL代码:.method private hidebysig static void Main(string[] args) cil managed{ .entrypoint // 代码大小 18 (0x12) .maxstack 3 .locals init ([0] int32 i) IL_0000: nop IL_0001: ldc.i4.3 IL_0002: stloc.0 IL_0003: ldloc.0 IL_0004: dup IL_0005: ldc.i4.1 IL_0006: add IL_0007: stloc.0 IL_0008: neg IL_0009: stloc.0 IL_000a: ldloc.0 IL_000b: call void [mscorlib]System.Console::WriteLine(int32) IL_0010: nop IL_0011: ret} // end of method Program::Main对于第二段的代码:using System;using System.Collections.Generic;using System.Text;namespace ConsoleApplication2{ class Program { static void Main(string[] args) { int i = 3; i = i++; Console.WriteLine(i); } }}IL代码:.method private hidebysig static void Main(string[] args) cil managed{ .entrypoint // 代码大小 17 (0x11) .maxstack 3 .locals init ([0] int32 i) IL_0000: nop IL_0001: ldc.i4.3 IL_0002: stloc.0 IL_0003: ldloc.0 IL_0004: dup IL_0005: ldc.i4.1 IL_0006: add IL_0007: stloc.0 IL_0008: stloc.0 IL_0009: ldloc.0 IL_000a: call void [mscorlib]System.Console::WriteLine(int32) IL_000f: nop IL_0010: ret} // end of method Program::Main i = 3 i = 3 i = -i++ i = i++ 打印i(结果为-3) 打印i(结果为3)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~IL_0000: nop IL_0000: nopIL_0001: ldc.i4.3 IL_0001: ldc.i4.3IL_0002: stloc.0 IL_0002: stloc.0IL_0003: ldloc.0 IL_0003: ldloc.0IL_0004: dup IL_0004: dupIL_0005: ldc.i4.1 IL_0005: ldc.i4.1IL_0006: add IL_0006: addIL_0007: stloc.0 IL_0007: stloc.0IL_0008: neg IL_0008: stloc.0 //差别就在这里,少了一个neg(即取负)IL_0009: stloc.0 IL_0009: ldloc.0IL_000a: ldloc.0 IL_000a: call IL_000b: call IL_000f: nopIL_0010: nop IL_0010: retIL_0011: ret 希望有人讲解一下,谢了先~! 查了一下MSDN,看懂了IL代码,但是却是知其然不知其所以然,知道IL代码表达的是什么意思,怎样产生的这个结果,但却不明白为什么会是这个样子的,请高人指点。另外,对于为什么在Dev C++中运行“i = -i++”时,得到的结果和TurboC的结果一样,都是“-2”;但是对在Dev C++中运行“i = i++”的结果却又反过来和C#一样,都为“3”。这一点,依然很是迷惑~!还请高人指点。 i++这个东西只有在语句结束时才实现自增操作,也就是说在执行完赋值i=i++;这个操作后i的值才变化 i=i++,先执行i=i, ++如果不循环回来就永远不会调用,有别于 i=++i @johnny1983() 不管如何,总之在语句结束后,还是要把i加1的,但是在后面的打印时,他确依然是-3或3,根本没有见++的操作效果 正常,C#是先计算表达式的值,然后再执行自增操作。所以int i = 3;i = -i++;这里 -i++作为表达式,其值是-3,然后进行自增,i变成4,最后赋值,则i = -3。C#对于同一个表达式,不同的版本的编译器总是得到确定的结果,而C++这个是未定义的操作,不同的编译器结果是不同的。C#有一个很重要的概念在于中间值,即表达式的一旦被计算完毕,则这个表达式再发生改动也不会影响这个计算结果。同样的如returnpublic static int MyMethod(){ try { int i = 2; return i; } finally { i = 3; }}返回值是2 i = i++或类似的表达式:i = f( i++ ),在C++是未定义的操作,没有人知道i会是什么…… 不管如何,总之在语句结束后,还是要把i加1的,但是在后面的打印时,他确依然是-3或3,根本没有见++的操作效果----------------------------------IL的代码........ IL_0000: nop IL_0001: ldc.i4.3 //将3压入栈 IL_0002: stloc.0 //3出栈 IL_0003: ldloc.0 //3再次压栈 IL_0004: dup //复制栈上当前最顶端的值,然后将副本推送到栈上,就是再压一次3。 IL_0005: ldc.i4.1 //将1压入栈,此时栈上有1,3,3,一共3个值 IL_0006: add //栈顶上两个值弹出,然后相加,把结果堆栈,此时栈上值为4,3 IL_0007: stloc.0 //4出栈 IL_0008: neg //3出栈取反,然后压栈 IL_0009: stloc.0 //-3出栈 IL_000a: ldloc.0 //-3入栈 IL_000b: call void [mscorlib]System.Console::WriteLine(int32) //调用函数,参数为栈内元素,就是-3。 IL_0010: nop IL_0011: ret //返回这样看就清楚了点吧,4作为临时变量在取反前就消失了。 //调用函数,参数为栈内元素,就是-3。为避免混淆说明下,这里是为了保护断点局部变量压栈,函数调用的时候读取的应该是局部变量索引的数值,不过就值来说这两个是一样的。 IL_0001: ldc.i4.3 //将3压入栈 IL_0002: stloc.0 //3出栈 IL_0003: ldloc.0 //3再次压栈这三句的意思实际是在局部变量索引0(就是i)设为3。并不是没有意义的。 IL_0007: stloc.0 //4出栈 IL_0008: neg //3出栈取反,然后压栈 IL_0009: stloc.0 //-3出栈 IL_000a: ldloc.0 //-3入栈而在这里,4出栈到局部变量索引0(就是i)然后i就被-3所覆盖了。 ◎Ivony◎Fortner(好想退休) 谢谢你们的讲解,让我有种醍醐灌顶的感觉。~~~~~~~~~~~~~~~~~~~~我做了一下总结放在Blog上了:http://www.cnblogs.com/BISer/archive/2007/07/25/831417.html 如何把“11/14/10 18:14:35”转换成系统认可的时间格式? 求简单的ADO.NET例子 关于多个控件共用一个事件的问题 WinForms 窗体自动收缩问题~! 谁有VS2005 C# 的例子? ( 答者有分 ) .net2.0 web发布问题 C/S项目要求 文件操作(TXT,XML) 那位给个Microsoft.Web.UI.WebControls.dll文件,我在网上下载的IEWebControls.exe老是生成不了这个dll文件 关于菜单和工具栏 C#的时间函数 Web窗体内的控件访问不到 怎么把数据表一行一行的读
~~~~~~~~~~~~
int i =3;
i = i++;
打印i的值;
~~~~~~~~~~~~在TurboC2.0中的结果是4,在Dev C++中的结果是3,在VS2005中的结果是3。
~~~~~~~~~~~~
int i =3;
i = i++;
打印i的值;
~~~~~~~~~~~~
我认为是i先赋值给i,然后i再执行++,在内存中,只有一个i,所以这里有一个++的操作,所以就应该是4啊??
using System;
using System.Collections.Generic;
using System.Text;namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
int i = 3;
i = -i++;
Console.WriteLine(i);
}
}
}IL代码:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// 代码大小 18 (0x12)
.maxstack 3
.locals init ([0] int32 i)
IL_0000: nop
IL_0001: ldc.i4.3
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: dup
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: stloc.0
IL_0008: neg
IL_0009: stloc.0
IL_000a: ldloc.0
IL_000b: call void [mscorlib]System.Console::WriteLine(int32)
IL_0010: nop
IL_0011: ret
} // end of method Program::Main对于第二段的代码:
using System;
using System.Collections.Generic;
using System.Text;namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
int i = 3;
i = i++;
Console.WriteLine(i);
}
}
}IL代码:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// 代码大小 17 (0x11)
.maxstack 3
.locals init ([0] int32 i)
IL_0000: nop
IL_0001: ldc.i4.3
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: dup
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: stloc.0
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: call void [mscorlib]System.Console::WriteLine(int32)
IL_000f: nop
IL_0010: ret
} // end of method Program::Main
i = -i++ i = i++
打印i(结果为-3) 打印i(结果为3)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
IL_0000: nop IL_0000: nop
IL_0001: ldc.i4.3 IL_0001: ldc.i4.3
IL_0002: stloc.0 IL_0002: stloc.0
IL_0003: ldloc.0 IL_0003: ldloc.0
IL_0004: dup IL_0004: dup
IL_0005: ldc.i4.1 IL_0005: ldc.i4.1
IL_0006: add IL_0006: add
IL_0007: stloc.0 IL_0007: stloc.0
IL_0008: neg IL_0008: stloc.0 //差别就在这里,少了一个neg(即取负)
IL_0009: stloc.0 IL_0009: ldloc.0
IL_000a: ldloc.0 IL_000a: call
IL_000b: call IL_000f: nop
IL_0010: nop IL_0010: ret
IL_0011: ret 希望有人讲解一下,谢了先~!
所以int i = 3;
i = -i++;这里 -i++作为表达式,其值是-3,然后进行自增,i变成4,最后赋值,则i = -3。C#对于同一个表达式,不同的版本的编译器总是得到确定的结果,而C++这个是未定义的操作,不同的编译器结果是不同的。C#有一个很重要的概念在于中间值,即表达式的一旦被计算完毕,则这个表达式再发生改动也不会影响这个计算结果。同样的如returnpublic static int MyMethod()
{
try
{
int i = 2;
return i;
}
finally
{
i = 3;
}
}返回值是2
----------------------------------
IL的代码........
IL_0000: nop
IL_0001: ldc.i4.3 //将3压入栈
IL_0002: stloc.0 //3出栈
IL_0003: ldloc.0 //3再次压栈
IL_0004: dup //复制栈上当前最顶端的值,然后将副本推送到栈上,就是再压一次3。
IL_0005: ldc.i4.1 //将1压入栈,此时栈上有1,3,3,一共3个值
IL_0006: add //栈顶上两个值弹出,然后相加,把结果堆栈,此时栈上值为4,3
IL_0007: stloc.0 //4出栈
IL_0008: neg //3出栈取反,然后压栈
IL_0009: stloc.0 //-3出栈
IL_000a: ldloc.0 //-3入栈
IL_000b: call void [mscorlib]System.Console::WriteLine(int32) //调用函数,参数为栈内元素,就是-3。
IL_0010: nop
IL_0011: ret //返回这样看就清楚了点吧,4作为临时变量在取反前就消失了。
IL_0002: stloc.0 //3出栈
IL_0003: ldloc.0 //3再次压栈这三句的意思实际是在局部变量索引0(就是i)设为3。并不是没有意义的。 IL_0007: stloc.0 //4出栈
IL_0008: neg //3出栈取反,然后压栈
IL_0009: stloc.0 //-3出栈
IL_000a: ldloc.0 //-3入栈
而在这里,4出栈到局部变量索引0(就是i)
然后i就被-3所覆盖了。
◎Fortner(好想退休) 谢谢你们的讲解,让我有种醍醐灌顶的感觉。
~~~~~~~~~~~~~~~~~~~~
我做了一下总结放在Blog上了:http://www.cnblogs.com/BISer/archive/2007/07/25/831417.html