求解一个C#语法的怪问题

问题描述

有一段很简单的代码:inta=10;a=a++这段代码在c#下编译执行后a仍然=10;而按c++语法执行后a=11请牛人给予解释本人之前认为在c#下编译执行后应该为11,a应该只指向了同一块内存空间呀

解决方案

解决方案二:
看来楼主应该好好了解下C#值类型和引用类型的区别
解决方案三:
a++是先赋值,再运算(这语句等效于a=10;a++;)++a是先运算,再赋值(这语句等效于a++;a=11;)这是基本内容啊!
解决方案四:
不认真看书的结果...
解决方案五:
++运算符(C#参考)增量运算符(++)将操作数加1。增量运算符可以出现在操作数之前或之后:备注第一种形式是前缀增量操作。该操作的结果是操作数加1之后的值。第二种形式是后缀增量操作。该运算的结果是操作数增加之前的值。数值类型和枚举类型具有预定义的增量运算符。用户定义的类型可重载++运算符。在枚举时通常允许整型运算。示例复制代码//cs_operator_increment.csusingSystem;classMainClass{staticvoidMain(){doublex;x=1.5;Console.WriteLine(++x);x=1.5;Console.WriteLine(x++);Console.WriteLine(x);}}输出2.51.52.5*****************************************************************************欢迎使用CSDN论坛专用阅读器:CSDNReader(附全部源代码)http://www.cnblogs.com/feiyun0112/archive/2006/09/20/509783.html
解决方案六:
和C++的运算规则不一样。要分开对待。两者只是相似,绝不等同。
解决方案七:
C#下结果如下:inta=10;a++;++a;//与上句等同MessageBox.Show(a.ToString());///////////////结果都为11inta=10;a=a++;MessageBox.Show(a.ToString());////////////结果为10
解决方案八:
补充说明一下:a++与++a的结果是相同的!也就是四楼所说的增量运算符(++)将操作数加1。增量运算符可以出现在操作数之前或之后:
解决方案九:
又看了一下感觉楼上诸位对困扰楼主的问题理解有误,我以为楼主认为inta=10;a=a++;会得到a=11,是因为C++中a=和a++都是对同一块内存空间进行的运算而在C#中,int做为值类型在运算的时候传递的是一个副本也就是说这个式子,先建立一个a的副本,然后把副本的值赋给a,再对副本进行自增的操作最后的结果和先赋值还是先自增并没有关系,如果是对a本身的操作,自增后的结果都会是11的
解决方案十:
++a是前缀增量操作...该操作的结果是操作数加1之后的值...此时++a==11,此后a=11...a++是后缀增量操作...该运算的结果是操作数增加之前的值...此时a++==10,此后a=11...a=a++;等同于a=10;...结果...注意是结果...
解决方案十一:
上面解釋已經很清楚了,不再蕾書!
解决方案十二:
楼主应该换成这样inta=10;intb=a++;那么就清楚很多了。
解决方案十三:
事实上:inta=10;a=a++;Console.Write(a);输出的是10inta=10;intb=a++;Console.Write(a);输出的是11
解决方案十四:
这个问题问的好,学了不少东西,也多谢8楼的解释,该死的.net运行机制跟C的都不一样了
解决方案十五:
又研究了一下,8楼的答案有问题。在C#中,a=a++;的执行过程是先做一个a的副本值为10,然后对a做++操作,此时a值为11,然后再把那个副本的值10赋给a,a的值就是10了。而C++中,a=a++;的执行顺序是:先做一个a的副本值为10,然后把副本值10赋给a,a还为10,然后执行++,a的值就变为11了。这回应该解释清楚了,呵呵!
解决方案:
嗯,具体的过程确实应该和楼上的一样
解决方案:
被后缀自增描述的先操作后自增过程给忽悠了
解决方案:
谢谢楼上各位的讨论我刚才看了下中间代码c#编译器下的中间代码:inta=10;00000027movesi,0Aha=a++;0000002cmovedi,esi-------将a的值移入一个寄存器0000002eincesi-------执行++操作0000002fmovesi,edi-------再将临时寄存器的值覆盖回来感觉在c#编译器下++写在后面的时候,不太看得懂中间代码的意思,整个就是折腾了一圈又回来c++编译器下的中间代码:inta=10;0041137Emovdwordptr[a],0Aha=a++;00411385moveax,dwordptr[a]--------先将a的值放入一个临时寄存器00411388movdwordptr[a],eax--------执行赋值操作0041138Bmovecx,dwordptr[a]--------再将赋值操作之后的a放入临时寄存器0041138Eaddecx,1--------在临时寄存器里执行++操作00411391movdwordptr[a],ecx--------最后把++计算结果再返回给指针ptr[a]C++编译器下,中间代码的逻辑很清楚
解决方案:
c#遇到对于值类型的赋值操作时,会先创建副本,然后用这个副本来进行真正的赋值并且从中间代码来看,c#中的++后缀似乎并没有很好的实现先赋值再加1的准则
解决方案:
c#里头b=a++是先把a的值保存在临时变量中然后a的值自加然后把临时变量的值给bc++里头b=a++是先把a放到一个临时变量中然后把临时变量赋给b然后a自加所以遇到a=a++的时候再c#中就是设一个临时变量c先c=a然后a++然后a=c所以a先自加了1然后右还原成原来的值在c++里头a=a++时先c=a然后a=c然后a++执行细节顺序不同而已可以看看楼上的反汇编
解决方案:
相信自己测试的结果,道理讲不讲都不重要
解决方案:
这是好贴,学到不少东西
解决方案:
a++是先赋值,再运算++a是先运算,再赋值
解决方案:
其实就是个执行顺序的问题
解决方案:
不错啊a++是先赋值,再运算++a是先运算,再赋值总之就是个执行顺序的问题
解决方案:
是啊,这个帖要顶的.没事也学习一下,学习成果如下:{inta=10;//a++;intb;b=a++;Console.WriteLine(b);Console.WriteLine(a);System.Console.ReadLine();}IL_0000:nopIL_0001:ldc.i4.s10IL_0003:stloc.0//存为ab=a++IL_0004:ldloc.0//参数入栈,用aIL_0005:dup//复制a,栈顶有两个连续的10值IL_0006:ldc.i4.1//加1IL_0007:addIL_0008:stloc.0//存为a,出栈IL_0009:stloc.1//存为b,出栈以上相当于:a1=a;//副本10a=a.add(1);//a=11b=a1//b=10,故即使把"b"换成"a",结果仍为10打印结果:IL_000a:ldloc.1//用b,打印出10IL_000b:callvoid[mscorlib]System.Console::WriteLine(int32)IL_0010:nopIL_0011:ldloc.0//用a,打印出11IL_0012:callvoid[mscorlib]System.Console::WriteLine(int32)IL_0017:nop若C++如17楼分析,则:b=a++;可能相当于:a1=a;//为自己创造一个替身a1参与表达式计算b=a1;//赋值到ba=a.add(1);//a入寄存器增1后赋值给a
解决方案:
++写在前面跟后面是有很大区别的
解决方案:
感谢25楼,我也跟你一样学习了,以下是终极答案楼主给出的代码classProgram{staticvoidMain(){inta=10;a=a++;}编译后成为exe文件,用微软自带的ildasm.exe打开它,观察其内部的il语句执行步骤.methodprivatehidebysigstaticvoidMain()cilmanaged{.entrypoint//代码大小11(0xb).maxstack3//初始化一个int32型变量a,其代号是0.localsinit([0]int32a)//空指令IL_0000:nop//ldc代表把一个数字常数压入堆栈。i4代表int32,s代表sum,10是sumIL_0001:ldc.i4.s10//从堆栈中弹出一个值,存入第0个变量,也就是存入变量a。//注意弹出堆栈的同时堆栈会消去该值,至此完成了第一句inta=10;IL_0003:stloc.0//将第0个变量压入堆栈IL_0004:ldloc.0//在堆栈上复制一个值,由于是a++,所以先保留变量a值的副本,然后再执行a的自增IL_0005:dup//把一个数字常数压入堆栈。i4代表int32,1代表数字1,只有1,2,4,8等数可以跳过sum方式IL_0006:ldc.i4.1//将堆栈上两个数字相加,消去堆栈上的这两个数字,再将结果压入堆栈IL_0007:add//将堆栈上的数字赋给第0个变量,消去堆栈上的这个数字,此时完成了a的自增,a值为11IL_0008:stloc.0//将堆栈上的数字赋给第0个变量,消去堆栈上的这个数字//这句是"="操作符的操作,将变量a自增前值的副本赋给"="左边的变量a,这样a值最终为10IL_0009:stloc.0//返回指令,它使得方法返回到调用现场。IL_000a:ret}//endofmethodProgram::Main有兴趣了解il中间语句的朋友,我将在稍后放上详尽的微软官方的资料,保证你能看懂每一句il代码,更加了解.net,请有兴趣的朋友加我QQ282898034
解决方案:
LZ你太有才了,不要一味的拿样比样,看事物要看本质,不同的环境要不同对待。
解决方案:
简单一些,lz看这段代码应该就懂了:inta=10;Console.WriteLine(a++);Console.WriteLine(a);输出1011Console.WriteLine(a++);先把a的值给输出来,然后再+1
解决方案:
好帖,学习了
解决方案:
先赋值,后自加
解决方案:
都告诉你们了,是先自加,后赋值,好好研究27楼再发言
解决方案:
又学到了新知识
解决方案:
Re:楼主  俺没看见牛人,只看见很多牛在天上飞,下边的人都在吹,自说自话的解释起来了a++和++a的区别,连楼主要问什么都没搞明白。  能提这么典型的问题,楼主当然懂得a++是什么意思,更不用别人解释a++和++a的区别,楼主显然明白。  楼主是问:  “本人之前认为在c#下编译执行后应该为11,a应该只指向了同一块内存空间呀”  这个问题非常典型,短短一句a=a++;既可以观察.net算术操作符优先级别,又可以观察++自增运算符的值复制机制,当然那是发生在临时堆栈上的,估计吹牛的人还不认识这个临时堆栈。  正如我在27楼解释的那样,a确实从头到尾只分配了一块内存空间,但此空间只是用来保存和提取a变量值,而不进行任何运算,在运算的时候,.net会另外开辟一个临时堆栈来做。  因为++自增运算符比=赋值运算符优先级高,所以顺序一定是:先做a的自增,再做赋值。  在a自增之前,因为考虑到a++对外表现的应当是a自增前的值,所以.net会在临时堆栈上提前复制一个a的值,稍后会用到。  这样临时堆栈上会出现两个10,新复制的那个10自增后变成11,先保存进了变量a的内存空间,同时出栈,这样a就成了11,临时堆栈上就只剩下了原来的那个10。  这时赋值运算符开始执行,临时堆栈里剩下的这个10就保存进了变量a的内存空间,同时出栈,这样a又变回10,临时堆栈也空了。  运算结束。  楼主原来以为会是11,我也以为是,因为我们看不到临时堆栈上的双胞胎a,从a=a++;语句字面上理解,还以为a自始至终只有一个,就像楼主说的同一块内存空间,所以才会误以为会是11。
解决方案:
很多人都是不看下面的回帖就发言的所以上面的解释成透明的了
解决方案:
学习啊,都是知识啊。大家都好牛。顶
解决方案:
支持34楼的
解决方案:
呵呵,看了楼上的发言真是学了不少东西,我学过C++和C#,不过没有注意这些细节,惭愧。。。看来还是楼主心细啊!顶一下!
解决方案:
来顶一个
解决方案:
来顶一个
解决方案:
支持34楼
解决方案:
高深啊,学习
解决方案:
语法这东西,也有很多细节需要深挖啊。
解决方案:
是啊是啊~嘿嘿学习学习!~
解决方案:
是啊,这个帖要顶的.没事也学习一下,学习成果如下:{inta=10;//a++;intb;b=a++;Console.WriteLine(b);Console.WriteLine(a);System.Console.ReadLine();}IL_0000:nopIL_0001:ldc.i4.s10IL_0003:stloc.0//存为ab=a++IL_0004:ldloc.0//参数入栈,用aIL_0005:dup//复制a,栈顶有两个连续的10值IL_0006:ldc.i4.1//加1IL_0007:addIL_0008:stloc.0//存为a,出栈IL_0009:stloc.1//存为b,出栈以上相当于:a1=a;//副本10a=a.add(1);//a=11b=a1//b=10,故即使把"b"换成"a",结果仍为10打印结果:IL_000a:ldloc.1//用b,打印出10IL_000b:callvoid[mscorlib]System.Console::WriteLine(int32)IL_0010:nopIL_0011:ldloc.0//用a,打印出11IL_0012:callvoid[mscorlib]System.Console::WriteLine(int32)IL_0017:nop若C++如17楼分析,则:b=a++;可能相当于:a1=a;//为自己创造一个替身a1参与表达式计算b=a1;//赋值到ba=a.add(1);//a入寄存器增1后赋值给a-------------------------------------------支持
解决方案:
C#这点的确让从C++来到人有点不适应
解决方案:
细节啊,细节
解决方案:
当我们说出的话让别人产生误解的时候,我们要考虑的是换个说法,而不是一味地嘲笑别人看不懂。当然,我觉得楼主问题拿来探讨很好,但如果我看到了我们部门有人在程序中这么使用的话,叫他改那是没话说的了。另:CSDN里真是有太多的回帖不看贴或者连帖子问题都看不懂就开始为别人指“阳光大道”的人了。
解决方案:
"++"或"--"放在变量前与放在变量后的意义是不一样的```如果"++"是放在变量前,那么程序执行的过程是:先运算,后符值.比如:inta=10,b;b=++a;程序执行结果为:a=11,b=11也就是说,当程序执行到"b=++a"语句时,先运算"++",既a=10+1=11;然后再通过符值运算符"="把a等于11的值符与b,这时b的值也就变为11了.如果"++"是放在变量后,那么程序执行的过程是:先符值,后运算.比如:inta=10;intb;b=a++;程序执行结果为:a=11,b=10也就是说,当程序执行到"b=a++"语句时,先把a等于10的值通过符值运算符"="符与b,这时b就有了一个初始值为10;然后程序在计算"++",把计算后的值符与a,即a=10+1=11.区别就是这样了,其实也好理解的,执行的顺序就向一般阅读一样,从左往右就OK了.ps:本人系初学者,如有说得不对的地方还望各位大侠指点啊,在此谢过大家了.
解决方案:
这里有详细解释:http://blog.csdn.net/yydy1983/archive/2007/06/29/1671107.aspxhttp://www.program-life.cn/Contents.aspx?id=95

时间: 2024-09-13 02:11:47

求解一个C#语法的怪问题的相关文章

集合-求解一个二分图,我不清楚这不是不一个二分图,求help

问题描述 求解一个二分图,我不清楚这不是不一个二分图,求help 有N个项目(p)需要评审,每个项目必须要有x个专家(e)来评,每个专家要最多评y个专家,那么专家的数量是:N * x / y,假设这个数字是M,那么项目与专家的关系数为:N * x,或者M * y,N * x = M * y.因为项目和专家都是有分类的,所以对于每个项目来说,选择专家的时候是有权重的,即优先选择同分类的专家,然后根据分类的相近程度选择.假设对于每一个项目来说,备选专家集合都已经按照权重排序了那么怎么样分配,能使每个

(JS-匿名函数-闭包)求解一个问题,估计是作用域

问题描述 (JS-匿名函数-闭包)求解一个问题,估计是作用域 今天想写一个直接用JS替代JQ的delegate的方法,结果发现在闭包中出现了问题!示例:var x1 = function(){alert(11);}(function(){alert(1);}())求解为什么这段代码的输出是1,然后还会输出11?var x1 = function(){alert(11);}(function(){alert(1);})()然后是这段代码,为什么输出是11?并且1不会输出?var x1 = func

求解一个关于java的问题

问题描述 求解一个关于java的问题 这里的temp在前面没有被定义,也没声明,为什么能被使用??如图 解决方案 定义对象的同时可以给对象进行一些赋值的操作 解决方案二: 定义了啊同学Course temp = xxxx那不是定义么 解决方案三: 你想表达啥?没懂你意思呢?Course temp 不是在声明吗? 解决方案四: 一个问题求解Java动态规划求解最长公共子串问题一个搜索问题的求解 解决方案五: 看来这个是连对象都不知道是什么的同志 解决方案六: 定义了 Course cr = new

aes对称加密解密-求解一个 单表替代密码 和aes加密解密 c++代码

问题描述 求解一个 单表替代密码 和aes加密解密 c++代码 如题 要用vs2015做 最好一天内搞定 简单易懂 小白急用 解决方案 AES加密算法(C++实现,附源码) http://download.csdn.net/detail/cleopard/7245981 单表置换密码的C++代码实现 http://download.csdn.net/detail/zjj7188/9301155 解决方案二: http://www.tuicool.com/articles/rMzuQrhttp:/

mvc-新手程序员,求解一个关于MVC验证登陆的问题

问题描述 新手程序员,求解一个关于MVC验证登陆的问题 想用服务器session来实现验证登陆状态的功能 业务逻辑代码如下 public User Login(string username,string pwd) { DAL.AboutUser au = new DAL.AboutUser(); User user = au.Login(username, pwd); if (user != null) { HttpContext.Current.Session["CurrentUser&qu

求解一个数据结构问题,希望用c++实现

问题描述 求解一个数据结构问题,希望用c++实现 题目是这样的: 设计一个算法,改造一个带头节点的双向链表,所有节点的原有次序保持在各个节点的rLink域中,并利用lLink域把所有节点按照从小到大的顺序链接起来. 解决方案 http://blog.chinaunix.net/uid-22556372-id-1773401.html 解决方案二: c++实现数据结构的细节问题

跪求大神帮忙解决一个java语法问题

问题描述 跪求大神帮忙解决一个java语法问题 有行代码编译总是不能通过,我觉得是语法问题,但是找了很久都找不出来啊.请大婶帮忙解决,感激不尽. 解决方案 你的代码呢?你的代码呢? 解决方案二: 1.请把您的问题要点尽量在标题说明,大神都很忙,有时不会点进来看内容,会先用标题过滤一下:2.就算大神今天闲下来,您这也没代码可看啊. 解决方案三: 检查 1. 单词 有没有写错,2.命名是否不符合要求3.语法问题 需要看代码 解决方案四: 编译不通过的问题大致分为两种,1,语法错误.2.ide(ecl

求解一个JAVA算法,关于固定地图路径的

问题描述 求解一个JAVA算法,关于固定地图路径的 求解,大神在哪里哇,我在想是不是要用A星算法的,不过A星算法不太适应这个地图,黑色的方框表示障碍物,不能穿过,空心圆表示可通过区域. 解决方案 可以考虑蚁群算法,,,,,,,,,,,,,, 解决方案二: 图片奉上 解决方案三: 在线等啊,急急急急急急急急 解决方案四: 在线等啊,急急急急急急急急 解决方案五: 要怎么用JAVA来实现这个算法,求解 解决方案六: 要怎么用JAVA来实现这个算法,求解

数学方程求解-求解一个数学方程1.45X-Z=56

问题描述 求解一个数学方程1.45X-Z=56 求解数学方程式如下: 1.45X-Z=56; 4.10Y-Z=56; Z=1.45X+4.10Y; 求解X;Y;怎么计算? 解决方案 你可以试着前面两个式子相减得到1.45x-4.10y=0或者4.10y-1.45x=0,再和第三式相加得到z=2个4.1y或者2个1.45x:当然我这个只是上学时候做数学题的套路 可能会有人有不一样的解题方法 解决方案二: 得不到唯一的解,有无穷多解. x取任意值,y=1.45/4.10x.z=2.9x 解决方案三: