【答案解析】常用的交换两个变量的值的方法中,一般会引入第三方变量,借助它来完成。如果要交换int型的a与int型的b的值,通常的方法是:
int temp=a;
a=b;
b=temp;
可是本题却不允许使用第三方变量,于是想到了以下几种方法来解决该问题。
(1)算术法
本方法利用普通的+与-运算符来实现,代码如下:
a=a+b;
b=a-b;
a=a-b;
以a=3,b=5为例,经过第一行语句的执行,a的值变为了3+5=8,b的值不变,仍然为5;经过第二行语句的执行,a的值不变,为8,b的值为8-5=3;经过第三行语句的执行,a为8-3=5,b的值不变,为3,达到了交换值的目的。
针对这种算法,是否可以将这种表达式更加精简呢?例如,通过执行语句a=a+b-(b=a),表面上看,该语句完全合法也可以达到交换的目的,而且此种方法在VC++6.0下编译可以实现交换。程序代码示例如下:
#include<stdio.h>
int main()
{
int a=3;
int b=5;
a=a+b-(b=a);
printf("%d%d/n",a,b);
return 0;
}
在VC下运行,程序输出结果:
5 3
但其实这是一种完全错误的做法,之所以VC++6.0能够运行正确,是因为这个问题是VC++6.0编译器一个自身的bug。对于该语句,首先b赋值为a,然后执行a的赋值语句a=a+b-(b=a)的时候,仍然减去的是b的值,而不是b赋值以后的a的值,所以a的值最终还是a。所以分析得到,这种情况下,实际输出应该为3和3。为了验证这一说法,在Visual Studio2005下运行上述代码,即可得出正确的结果。
(2)异或法
方法如下:
a=a^b;
b=a^b;
a=a^b;在分析上述代码时,首先看异或运算表(见表1),它是一个有关异或运算的表格。
表1 异或运算表
|
|
|
a
|
b
|
|
a=a^b
|
a^b
|
b
|
|
b=a^b
|
a^b
|
(a^b)^b
|
|
a=a^b
|
(a^b)^((a^b)^b)
|
(a^b)^b
|
接下来把结果化简,化简结果见表2。 第一步执行a=a^b,第二步执行b=a^b,将第一步带入,则根据以上步骤可以进行变换,(a^b)^b=a^(b^b)=a^0=a,可以看到,第二步完成以后b的值已经变成了a的值。第三步接着化简,a=a^b=(a^b)^((a^b)^b)=(a^b)^a=a^a^b=0^b=b,此时a也变成b了。通过以上3个步骤,最终实现了a与b的交换。
表2 化简结果表
|
|
0^0=0
|
a^a=0
|
|
0^1=1
|
b^b=0
|
|
1^0=1
|
0^a=a
|
|
1^1=0
|
0^b=b
|
除了以上这两种方法外,也有人提出过很多其他的方法,如通过指针地址操作来实现交换的目的,但由于这些方法太过于复杂,而且不太实用,此处就不再分析了,有兴趣的读者可以搜索相关资料进行更深层次的发散思维。