a = b + (b = a) * 0;

原创 2007年10月07日 20:15:00

这个语句看起来比较奇怪,在C#的编译器中,他的作用是交换a和b的值,而且不会产生数据溢出的问题

在C#的编译器中,对着运算符的执行顺序有着严格的定义,对每个运算符的运算方法也有着严格的定义。

首先读到的第一个运算符是赋值,这个运算符的优先级别比较低,所以继续向后执行,这时遇到遇到的运算符是+,+的方法是自左向右的,编译器把b的值入栈,正是因为这个原因,b的值在内存中被暂存了起来。

+号之后是一个括号,编译器开始对括号里的等式进行编译,a的值被压入了栈中,然后又出栈给了b变量,而对于后面的*0,因为任何数*0之后都会等于0,所以编译器直接就把这一步运算丢弃,同时也丢弃了+0这一步运算,这时就把b的值出栈赋给了a;

这个语句一切前提都是在C#的编译机制的前提下,+号是自左向右的,所以b的值将用入栈的形式被保存下来,而不是先去运算了括号内的赋值。

整个语句因为C#编译器的优化机制,产生的中间代码只有两次入栈,两次出栈,而把计算的步骤优化掉了。我们熟知的借用临时变量交换的方法的三次赋值,则是三次入栈三次出栈,用这个语句可以提高三分之一的效率,可惜的是 a = b + (b = a) * 0只能为数字的类型进行交换,这是局限所在。

一点题外话:
在软件工程学中,不提倡写这样的语句,但是这里对这个语句进行分析的目的,是为了学习C#的运算符运行规则。这个语句的原作者Invoy说得好:虽然在软作中我们不会这么写,但是能看懂这个句子并不是坏事。不过我最喜欢的倒是别外一句:如果说程序没有可读性,当一个语句被写进教科书的时候,可读性的问题也就不存在了。而类似于这种写法简短同时又有效率的语句是完全可以写进教科书的。

最后再写个例子说明运算符的方向规则
a = F(i) + G(i++) + H(i);
C#对+号的运算规则是从左到右,那么不管+右边的优先级有多高,也要把+左边的值计算了再入栈,所以这里i的三次取值,假如开始是3的话,F(i)中是3,G(i++)也是3,到H(i)中就是4了。
在C++中,不同的编译器对上式的运行结果不一样,我们说,这个语句会产生不确定的结果。而C#中严格的定义,我们可以使用这样的技巧。
什么,你说这样的话不能跨平台?拜托,C#是基于framwork的,那玩意儿天下只有一个。 

相关文章推荐

44b0 Mp3解码

  • 2015年10月06日 10:54
  • 3.21MB
  • 下载

S3C44B0X结构

  • 2013年07月21日 09:34
  • 2.06MB
  • 下载

漫步线性代数九——求Ax=0和Ax=b

前面的文章关注的是方阵的逆矩阵,Ax=bAx=b有一个解的话它就是x=A−1bx=A^{-1}b,它可以通过消元法得到。一个长方形矩阵带来的新的可能性——UU可能没有所有的主元,本文我们就将UU 化为...

MS-7584-0B.rar

  • 2014年10月31日 19:59
  • 3.78MB
  • 下载

redsn0w_win_0.9.15b3.zip

  • 2014年03月14日 14:21
  • 836KB
  • 下载

应用程序无法正常启动(0xc000007b)。请单击“确定”关闭应用程序 解决

重装系统 从32到64 重装了 vs2013 试试在vs2013上运行opencv 失败 显示 应用程序无法正常启动(0xc000007b)。请单击“确定”关闭应用程序 一开始以为是 符号...

IAR+44B0X的例子

  • 2013年07月16日 10:10
  • 30KB
  • 下载

44b0实验说明

  • 2013年12月04日 21:04
  • 1.73MB
  • 下载

win7下,令人头疼的 classpnp.sys (附带:安装系统时蓝屏;0x0000007b)。

前言: 1.      今天到单位,打开笔记本,发现启动后,程序报 appcrash 错误。       于是重启,使用安全模式进入,发现启动中停在  classpnp.sys 上, ...
  • sxzlc
  • sxzlc
  • 2011年12月26日 20:04
  • 38784
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:a = b + (b = a) * 0;
举报原因:
原因补充:

(最多只允许输入30个字)