写一个函数可以交换两个整形变量的内容。
方法一:
首先,想到的是定义一个第三变量进行两数的交换,假设两个整形变量为a、b,临时变量为temp,那么将a的内容赋值给temp,将b的内容赋值给a,再将temp的内容赋值给b,这样就完成了两数的交换。
在内存中申请一个4字节的空间存放num1的内容10,再申请一个4字节的空间存放num2的内容20,现在通过传参将两个数值交换,我们第一反应可能写出的是下面的函数,
void main()
{
int num1 = 10, num2 = 20;
printf("交换前:num1=%d num2=%d\n", num1, num2);
Swap(num1, num2);
printf("交换后:num1=%d num2=%d\n", num1, num2);
}
但是代码运行后,会发现并没有按照预期的操作进行两个数值的交换
出现此结果的原因在于在传参的时候进行的是传值操作,把num1的值传给形式参数a,把num2的值传给形式参数b,在Swap函数中交换了a和b的值,但是由于a,b和num1,num2的地址不同,他们所在空间不同,当函数执行完毕,num1、num2的值与a、b的值没有任何关系,num1、num2并未发生交换。
所以,应当避免这种错误写法,可以用传址调用的方法进行修正。
传值调用:
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
传址调用:
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。这种传参方式可以让函数和函数外边的变量建立起正真的联系,也就是函数内部可以直接操作函数外部的变量。
现将num1、num2的地址传给指针变量pa、pb,这样pa、pb所指的变量空间也就是num1、num2的内存空间。
void Swap1(int *pa, int *pb)
{
int temp = *pa;
*pa = *pb;
*pb = temp;
}
int main()
{
int num1 = 10, num2 = 20;
printf("交换前:num1=%d num2=%d\n", num1, num2);
Swap1(&num1, &num2);
printf("交换后:num1=%d num2=%d\n", num1, num2);
return 0;
}
代码对应的内存分配为
从执行结果可以看到,成功地交换了两数的值。
方法二:
上面的方法一需要定义一个临时变量,试想若不申请临时空间,可以进行数值的交换吗?
可以用加法来实现,对代码进行优化。
void Swap2(int *pa, int *pb)
{
*pa = *pa+*pb;
*pb = *pa-*pb;
*pa = *pa-*pb;
}
这种方法可以轻松地交换两个值,但是也有缺点存在,当num1、num2的值很大时,num1+num2就会超出整形所表示的范围,便不能进行交换。
方法三:
进一步优化,使用位操作符异或来操作。
void Swap3(int *pa, int *pb)
{
*pa = (*pa)^(*pb);
*pb = (*pa)^(*pb);
*pa = (*pa)^(*pb);
}
代码执行结果为:
可以看出,这种方法更为便捷地达到了预期的结果。