今天网上看到一个老套的编程题,就是“不用第三个变量进行两个变量的值交换”。是一个同学把java写的答案放在网上求别人解析一下。平时因为做题用的都是C++,所以好奇瞄了一眼,却发现实现方法与C++截然不同,并且,Java和C++算数表达式解析的机制也存在很大不同。好吧,我们先来看看这个例子吧。
Java实现:(本文出自:http://my.oschina.net/happyBKs/blog/416632)
public static void main(String[] args) {
// TODO Auto-generated method stub
int x=4;
int y=5;
x=y+(y=x)*0;
System.out.println("x="+x+", y="+y);
}
结果是:
x=5, y=4
这里我如果将表达式改为x=(y=x)*0+y;
那么结果就是 x=4, y=4
这个例子,我相信大家能猜出其中的原因:Java在解析表达式时是从左向右执行的。
详细地说,在这个赋值语句中,先执行右边的算数表达式。执行之前x=4, y=5
算术表达式又按照从左到右的顺序执行,最左边y+先执行。这时候 x=4, y=5.没有任何变化
右边是(y=x)*0再从左向右看,首先是(y=x),执行之后,x=4, y=4. y变了!
(y=x)*0显然是0。
(y=x)*0+y则是0+y=0+4=4,赋给了赋值表达式左边的x。这时候,x=5, y=4
那么,如果在C++中的话,会怎么样呢?
代码和结果是这样的:
#include <iostream>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char** argv) {
int x=4;
int y=5;
//x=(y=x)*0+y;
x=y+(y=x)*0;
printf("x=%d, y=%d",x,y);
system("pause");
return 0;
}
我将x=(y=x)*0+y;和x=y+(y=x)*0;两个表达式都实验了一下。结果答案都是:
x=4,y=4
这似乎说明了,在解析算数表达式时,执行不存在像Java那样的从左到右的顺序。同时,也不是从右向左的。
C++中的执行更像是这样一种情况执行了这样一个内联函数。(我推测的)
x=4,y=5
inline void fn(int x1, int y1)
{
x1=x;
y1=y;
y=x1;
x=y1+y1*0;
}
这似乎有点还是令人难以信服。那么我们就彻底跑个题吧,来看两个一样的代码例子,但是分别放到了Java和C++编译和运行环境中。
在java中的一个例子:
public static void main(String[] args) {
int a=1;
int b,c,d;
d=(b=a++)+(c=a++)+(a++);
System.out.println("a="+a+", b="+b+", c="+c+", d="+d);
}
运行结果:
a=4, b=1, c=2, d=6
在C++中:
#include "stdafx.h"
#include <stdlib.h>
int _tmain(int argc, _TCHAR* argv[])
{
int a=1;
int b,c,d;
d=(b=a++)+(c=a++)+(a++);
printf("a=%d, b=%d, c=%d, d=%d",a,b,c,d);
system("pause");
return 0;
}
运行结果:
上面的C++代码在gcc和VC下都进行了测试。
如果我把上面的例子再改一下。改为:
java:
public class TestMain {
public static void main(String[] args) {
int a=1;
int b,c,d;
d=(b=++a)+(c=++a)+(++a);
System.out.println("a="+a+", b="+b+", c="+c+", d="+d);
}
运行结果:
a=4, b=2, c=3, d=9
C++:
#include "stdafx.h"
#include <stdlib.h>
int _tmain(int argc, _TCHAR* argv[])
{
int a=1;
int b,c,d;
d=(b=++a)+(c=++a)+(++a);
printf("a=%d, b=%d, c=%d, d=%d",a,b,c,d);
system("pause");
return 0;
}
运行结果:
看到了吧。似乎这时候,C++表达式也存在了从左到右的特性。Java任然亘古不变。
是不是有点晕了,C++到底怎么了?
那么我们单独再为C++设置一个例子:这次咱们里面都是赋值。
int a=1, b=10, c=100, d=1000;
d=(b=a)+(c=b)+a;
printf("a=%d, b=%d, c=%d, d=%d",a,b,c,d);
system("pause");
return 0;
}
结果是:
在修改个例子:如果d=(b=a)+(c=b)+++a;
运行结果是:
从上面的例子中已经可以看出我们之前下的结论了:Java在解析算数表达式时是从左向右执行的。C++解析算数表达式时, ++在前的因式需要在计算时就结算,并且从左向右执行。而=赋值则更像是在调用一个封装了算术表达式和赋值功能的内联函数。++在后的变量的累加操作在整个大表达式计算完成得到值之后结算。(还是整个表达式赋值之后结算?其实是等价的)
本文来自云栖社区合作伙伴“开源中国”
本文作者:HappyBKs