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

本文介绍了一种在C#中不使用临时变量交换两个数值的方法,通过利用编译器的优化机制减少操作次数,提高效率。文章还探讨了该方法的工作原理及限制。

这个语句看起来比较奇怪,在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的,那玩意儿天下只有一个。 

### 比较两个C语言指针操作表达式的异同 #### 表达式分析 考虑给定的两个表达式: 1. `*a++ = *b++; *b++;` 2. `*a++ = *b++; *b+2` 这两个表达式涉及到了指针的操作以及解引用。 #### 解析第一个表达式 对于表达式`*a++ = *b++; *b++;`: - 首先执行的是赋值语句`*a++ = *b++`。这表示将`b`指向的内容复制到`a`所指向的位置,之后分别增加`a`和`b`使其各自指向下一个位置[^1]。 - 接着执行第二个部分`*b++`,这意味着进一步移动指针`b`至下一位,但并没有任何实际的数据被写入或读取。 ```c int main(){ int array_a[] = {0, 0}; int array_b[] = {1, 2}; int *a = array_a; int *b = array_b; *a++ = *b++; *b++; printf("%d %d\n",array_a[0],array_a[1]); } ``` #### 解析第二个表达式 针对表达式`*a++ = *b++; *b+2`: - 同样地,首先是赋值语句`*a++ = *b++`被执行,作用如同前一表达式描述的一致。 - 不过,在此之后是`*b+2`而不是另一个增量运算符(`++`)。这里只是简单计算了`b+2`的结果,并未改变原始指针`b`的位置也没有访问这个新地址处存储的数据。 ```c int main(){ int array_a[] = {0, 0}; int array_b[] = {1, 2}; int *a = array_a; int *b = array_b; *a++ = *b++; *b + 2; // This line does not modify b or access memory at b+2. printf("%d %d\n",array_a[0],array_a[1]); } ``` #### 主要差异总结 主要区别在于第二条指令的效果上: - 在第一条表达式中,第二次调用`*b++`确实改变了指针`b`的状态,使得其向前推进了一位。 - 而在第二条表达式里,`*b+2`仅仅是一个算术上的偏移量计算,既不会影响到原指针也不会引起内存中的数据变动。 因此,尽管两者看起来相似,但由于最后一个操作的不同,最终的行为会有显著差别。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值