使用C语言实现两数交换
对于两个整型变量a和b,假设a=3,b=4,我们怎么实现交换它们的值呢?
预备知识:*符号和&符号
在C语言中,*
除了代表乘法运算,还代表指针运算,&
代表取地址操作。*后面必须跟指针变量,而&则无特殊要求。
什么是指针?指针其实就是指内存地址,而指针变量就是用来存储内存地址的变量,即这个指针变量的值即为一个内存地址。
我们来看一个示例
#include <stdio.h>
int main()
{
int x=123;
int *p;//定义一个整型指针变量,p用来存储一个整型变量的地址
p=&x;
printf("变量x的地址即p的值为:%d\n",p);
printf("&x=%d\n",&x);
printf("*p=%d\n",*p);
return 0;
}
输出如下
变量x的地址即p的值为:-9876
&x=-9876
*p=123
前面两个输出毫无疑问,但是为什么*p=123呢。因为在C语言中,我们int *p;
来表示生成一个指针变量p,p的值就是指针变量存储的地址,p就代表这个地址上对应的数据,因为变量x的值为123,它存储在存储单元-9876里面,那么输出p就代表输出存储单元-9876上的值123.
实现两数交换
接下来我们就用指针变量和&取地址符实现两数交换,直接上代码
#include <stdio.h>
void swap1(int *a,int *b)
{
int tmp=*a;
*a=*b;
*b=tmp;
}
void swap2(int *a,int *b)
{
*a=*a+*b;
*b=*a-*b;
*a=*a-*b;
}
void swap3(int *a,int *b)
{
*a=(*a)^(*b);
*b=(*a)^(*b);
*a=(*a)^(*b);
}
void swap4(int *a,int *b)
{
*a=*a+*b-(*b=*a);
}
int main()
{
int a=3;
int b=4;
swap1(&a,&b);
printf("a:%d,b:%d\n",a,b);
swap2(&a,&b);
printf("a:%d,b:%d\n",a,b);
swap3(&a,&b);
printf("a:%d,b:%d\n",a,b);
swap4(&a,&b);
printf("a:%d,b:%d\n",a,b);
return 0;
}
运行结果如下
a:4,b:3
a:3,b:4
a:4,b:3
a:3,b:4
下面我们来一一讲解着四个实现两数交换的函数
swap1
在swap1函数中,我们传入的实参为两个变量的地址,那么在函数中自然需要两个指针变量来作为形参存储地址,所以使用函数时对变量应用取地址符号&,而函数形参那里为指针变量,其实这是实现两数交换的基础(四个swap函数皆是如此),只有这样,我们传入main函数里变量的地址,才能对其实现值的变化,否则只传入值,会造成在swap函数中生成临时变量,对临时变量的操作不会影响main函数中的变量的值。
在这个函数中,我们通过一个临时整型变量tmp先存储指针变量a对应内存单元上存储的值,再把指针变量b对应内存单元上的值赋给a,即把指针变量a对应内存单元上的值变为4,再把tmp存储的最开始a的值3赋给*b,这样就实现了两数交换。
swap2
就是通过加减法实现两数交换,不过这个不容易想到。
swap3
通过计算机异或操作实现两数交换。
我们知道,在二进制中,1和0异或得到1,1和1异或得到0,0和0异或得到0,即恰好只有一个为真时才为真。
又因为数字在计算机中是按二进制进行计算的,通过这个原理,我们就可以实现两数交换。
swap3的3次异或计算过程如下:
——————————————
0011–>a最初
0100–>b最初
——————
0111–>a(第一次异或的值赋给a)
0100–>b
——————
0011–>b(第二次异或的值赋给b)
0111–>a
——————
0100–>a(第三次异或的值赋给a)
———————————————
经过三次异或操作,a由0011即3变为0100,b由0100即4变为0011
swap4
在我的理解中,函数4巧妙利用了缓冲区的机制
对式子*a=*a+*b-(*b=*a)
,先计算(*b=*a)
,但是计算结果留在缓冲区,没有改变内存单元中*b
的值,然后计算*a=*a+*b-*a
,这里的*b
仍是从内存单元中取值,这时,在缓冲区中,有*a=3
,*b=4
,再赋值到内存单元上,实现了两数交换