不用临时变量交换两个数的值(C实现)
2009-12-25 15:13
447 查看
当要交换两个数的值时,通常的做法是定义一个临时变量,然后再进行交换。那么能不能不用临时变量而交换两个数的值呢?可以的!C语言提供的异或运算就可以实现这样的操作。
异或运算符^也称XOR运算符,它的规则是若参加运算的两个二进位同号,则结果为0(假);异号为1(真)。即0 ^ 0 = 0, 0 ^ 1 = 1, 1 ^ 0 = 1, 1 ^ 1 = 0。
例:
这下就清楚了,原来程序运行时先把逗号左边表达式的值计算出来丢弃掉,然后再做其它的运算,最开始的错误也就错在了这里。
好了,既然上面的式子有问题,那有没有其它正确的方法能一条语句实现三个变量的值的交换呢?恕本人愚钝,还没有想出来。如果谁知道,请给我留言。在此先致谢!
还有一个问题,就是交换三个变量的值(每个变量值都要改变)应该有两种情况,123可以变为231或312。我当时想到过,只是觉得可以类比就没有说明,现在看来可能会误导读者,这里说明一下。
[/code]
异或运算符^也称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]
相关文章推荐
- 不用临时变量实现两个数的交换
- 不用临时变量,实现两个数的交换
- C语言实现 不允许创建临时变量,交换两个数的内容
- 不用临时变量交换两个数的值
- 不用临时变量交换两个数的值
- 用异或运算符实现不用第三个临时变量交换两个变量的值
- 不用临时变量直接交换两个数的值
- c语言不用临时变量交换两个数程序分析
- 不用临时变量交换两个数(离散、位运算)
- 不用临时变量交换两个数的值
- 不用临时变量交换两个数的值
- 程序员面试金典——解题总结: 9.17中等难题 17.1编写一个函数,不用临时变量,直接交换两个数
- 不用临时变量,直接交换两个数
- 不用临时的变量 交换两个数的两种方法
- 不用临时变量 实现两个变量之间的数据交换
- Java不用临时变量temp将两个数交换(面试题)
- 不用临时变量交换2个数的3种实现
- C/C++/Java不使用临时变量实现两个数的交换
- 交换两个数的内容(交换两个变量的内容,编程实现。(如果不允许创建临时变量呢?))
- 不用临时变量交换两个数的值