您的位置:首页 > 其它

不用临时变量交换两个数的值(C实现)

2009-12-25 15:13 447 查看
当要交换两个数的值时,通常的做法是定义一个临时变量,然后再进行交换。那么能不能不用临时变量而交换两个数的值呢?可以的!C语言提供的异或运算就可以实现这样的操作。

异或运算符^也称XOR运算符,它的规则是若参加运算的两个二进位同号,则结果为0(假);异号为1(真)。即0 ^ 0 = 0, 0 ^ 1 = 1, 1 ^ 0 = 1, 1 ^ 1 = 0。

例:
#include <stdio.h>

int main(int argc, char *argv[])
{
int a = 2, b = 6;

a = a ^ b;
b = b ^ a;
a = a ^ b;

printf("a = %d b = %d/n", a, b);

return 0;
}

结果如下: a = 6 b = 2

分析:前两个赋值语句:“a = a ^ b;”和“b = b ^ a;”相当于b = b ^ (a ^ b),而b ^ a ^ b等于a ^ b ^ b。b ^ b的结果为0,因为同一个数与相向相^,结果必为0。因此b的值等于a ^ 0,即a,其值为2。

再执行第三个赋值语句:“a = a ^ b”。由于a的值等于(a ^ b),b的值等于(b ^ a ^ b),因此,相当于a = a ^ b ^ b ^ a ^ b,即a的值等于a ^ a ^ b ^ b ^ b,等于b。

另外两种方法:

方法一:

void swap(int *p, int *q)
{
*p = *p + *q;
*q = *p - *q;
*p = *p - *q;
}

[code]方法二:

void swap(int *p, int *q)
{
*p = *p + *q - (*q = *p);
}

原理为算术运算符的结合顺序为自左至右。

注:可以把异或的三条语句压缩为一条:a ^= b ^= a ^= b;

要交换三个变量的值,用下面变量会报错:c = a + c - (a = b, b = c);

下面来分析一下,先看一个示例程序,如下:

#include <stdio.h>

int main(int argc, char *argv[])
{
int a = 1;
int b = 2;
int c = 3;

c = a + c - (a = b, b = c);

printf("a = %d/n", a);
printf("b = %d/n", b);
printf("c = %d/n", c);

return 0;
}

编译运行,结果如下:a = 2 b = 3 c = 2

可见,最初目标中的c = 1部分没能实现。于是分析原因:

《The C Programming Language·Second Edition》P205介绍说,“The additive operators + and - group left-to-right”,即附加运算符加号和减号的结合顺序是自左向右;P209介绍说,“A pair of expressions separated by a comma is evaluated left-to-right, and the value of the left expression is discarded. The type and value of the result are the type and value of the right operand”,即逗号表达式的计算顺序是从左向右,逗号左边表达式的值被舍弃,表达式结果的类型和数值是逗号右边表达式的类型和数值。

既然如此,那结果应该是正确的,为什么还会出错呢?再来看一下VC6.0下编译产生的汇编代码:

7: int a = 1;
00401028 mov dword ptr [ebp-4],1
8: int b = 2;
0040102F mov dword ptr [ebp-8],2
9: int c = 3;
00401036 mov dword ptr [ebp-0Ch],3
10:
11: c = a + c - (a = b, b = c);
0040103D mov eax,dword ptr [ebp-8]
00401040 mov dword ptr [ebp-4],eax
00401043 mov ecx,dword ptr [ebp-4]
00401046 add ecx,dword ptr [ebp-0Ch]
00401049 mov edx,dword ptr [ebp-0Ch]
0040104C mov dword ptr [ebp-8],edx
0040104F sub ecx,dword ptr [ebp-8]
00401052 mov dword ptr [ebp-0Ch],ecx

可以看到,第11行代码的执行过程如下:

先把b的值赋给a,再把a和c的值相加,结果放在寄存器ecx中,然后把c的值赋给b,最后再把ecx与b的值相减,结果赋给c。分解为C语句为:

[code]a = b; /* a = 2, b = 2 */
ecx = a + c; /* ecx = 5, a = 2, c = 3 */
b = c; /* b = 3, c = 3 */
c = ecx - b; /* c = 2, ecx = 5, b = 3 */

这下就清楚了,原来程序运行时先把逗号左边表达式的值计算出来丢弃掉,然后再做其它的运算,最开始的错误也就错在了这里。

好了,既然上面的式子有问题,那有没有其它正确的方法能一条语句实现三个变量的值的交换呢?恕本人愚钝,还没有想出来。如果谁知道,请给我留言。在此先致谢!

还有一个问题,就是交换三个变量的值(每个变量值都要改变)应该有两种情况,123可以变为231或312。我当时想到过,只是觉得可以类比就没有说明,现在看来可能会误导读者,这里说明一下。

[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: