为什么我的交换函数不起作用?


前言

不少学习c语言的小白在写交换函数时都会碰到这样一个问题:明明在函数里已经进行了数值交换,但是输出的值并没有改变,还是之前的值。这是为什么呢?让我们一起来分析一下吧。


一、错误示范

我们初学者会想当然的用形参进行数值交换的操作,下面是演示代码:

void Swap1(int x, int y)
{
    
    
	int tmp = 0;
	tmp = x;
	x = y;
	y = tmp;
}
int main()
{
    
    
	int a = 10;
	int b = 20;
	printf("交换前:     a=%d  b=%d\n", a, b);
	Swap1(a, b);
	printf("Swap1交换后:a=%d  b=%d\n", a, b);
	return 0;
}

输出结果:
在这里插入图片描述
我们发现,a和b的值并没有进行交换,为什么呢?函数里明明已经进行交换了呀?这样做的朋友就是对函数参数的传递理解还不够透彻,我们首先来理解一下函数的实参和形参。

1.实参

真实传给函数的参数,叫实参。实参可以是:常量、变量、表达式、函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。

2.形参

形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。

    int a = 10;
	int b = 20;
	Swap1(a, b);

这里的a和b是确定的值,叫做实参,把他们传递给函数进行下一步操作。

void Swap1(int x, int y)

这里的x和y就是形参,用于接收 Swap1(a, b) 传递过来的参数,然后进行相应的处理,但是处理完以后变量就会自动销毁。这跟局部变量类似,只在局部的范围内起作用,用完就销毁了。而 Swap1函数返回值类型是void,没有返回任何值,所以最终的输出还是原来的a和b的值,没有发生任何改变。

也可这么理解,形参只是实参的一份拷贝,它们都有自己的独立空间,函数内部只是对拷贝的参数进行操作而不会影响到实参的数值。下图是调试状态下的监视窗口,我们可以看到两点重要的信息:

  1. 分别查看了a,b和x,y的地址,它们并不相同,所以x,y的改变并不影响a,b。
  2. 当程序走出函数体时,x,y都变成了灰色,表示已经被销毁了,这也印证了我们之前所说的结论。

在这里插入图片描述

二、正确示范

分析出了错误原因,接下来既然好办了。我们要找到a和b的地址,然后再改变其对应的值,这样才能达到真正的交换目的。以下是正确的代码:

void Swap2(int* px, int* py)
{
    
    
	int tmp = 0;
	tmp = *px;
	*px = *py;
	*py = tmp;
}
int main()
{
    
    
	int a = 10;
	int b = 20;
	printf("交换前:       a=%d  b=%d\n", a, b);
	Swap1(a, b);
	/*printf("Swap1交换后:a=%d  b=%d\n", a, b);*/
	Swap2(&a, &b);
	printf("Swap2交换后:  a=%d  b=%d\n", a, b);
	return 0;
}

输出结果:
在这里插入图片描述

这里涉及到了指针的用法,所谓指针就是地址的一个标记,举个通俗的例子。你去上课的时候,首先要找到教室在哪,你才能上课,而为了方便找到教室,每间教室都会进行相应的编号,如E405就表示E楼的4层第5间教室,有了这个编号你就可以找到教室,找到教室以后,你可以对教室里的布局进行改变,例如你可以改变教室里的桌子数量。同样道理,在程序里你可以通过地址找到a和b,然后可以改变其对应的值。

调试程序后,我们发现a,b的地址和px,py的地址一模一样,说明函数已经定位到了a和b的空间,接下来只需要对相应的值进行交换,程序就能正确输出了。


三、总结

我们来进行总结,通过一个小小的交换函数,我们用到了很多知识,首先是函数的调用,涉及到实参和形参的使用,如果不理解清楚,很容易会出现逻辑上的错误。其次我们还学会用指针进行传参,这样就能真正的改变参量的值。所以学习还真不能只看到表面现象,理解到其背后的意义也是很重要的。

猜你喜欢

转载自blog.csdn.net/weixin_42907822/article/details/113354405
今日推荐