【详解】指针与函数传参——多图、多例子(c语言)
前言在用c语言实现链表时,会有很多朋友无法理解明明传了指针到函数中,函数中对指针改变却无法影响原函数中指针的位置,事实上,这是因为你对形参和实参的关系理解还不够透彻。通过这篇文章,我将告诉你指针传参时,函数的形参到底该选择怎样的类型接收。1.函数的实参与形参实际参数(实参)真实传给函数的参数叫实参。实参可以是常量、变量、指针甚至函数等。无论实参是何种类型的量,在进行函数调用时,他们都必须有确定的值
前言
在用c语言实现链表时,会有很多朋友无法理解明明传了指针到函数中,函数中对指针改变却无法影响原函数中指针的位置,事实上,这是因为你对形参和实参的关系理解还不够透彻。通过这篇文章,我将告诉你指针传参时,函数的形参到底该选择怎样的类型接收。
目录
1.函数的实参与形参
1.1实际参数(实参)
真实传给函数的参数叫实参。
实参可以是常量、变量、指针甚至函数等。
无论实参是何种类型的量,在进行函数调用时,他们都必须有确定的值,一边把这些值传给形参。
1.2形式参数(形参)
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。
总结来说二者的关系就是:形参是实参的一份临时拷贝,形参的改变无法影响实参,而形参只在所调用函数中有效,且一出函数就会被销毁。
来看个例子:
void function(int a)
{
a = 6;
}
int main()
{
int x = 8;
function(x);
return 0;
}
这里的x就是实参,而a就是形参
function函数调用前:实参已经建立并赋值
function函数调用:拷贝形参
function函数调用(a=6):形参a改变,"a = 6"
function函数调用完成:形参销毁,实参并不改变
(形参具体如何被创建和销毁可以参看文章——函数栈帧详解,这里就不过多赘述)
2.指针与函数
前面的内容相信大部份读者都能明白,接下来我会以同样的方式为大家讲解一级指针与二级指针传参,相信看完你就能彻底明白指针我们到底该如何正确的向函数传递指针,以改变自己想要改变的内容。
2.1一级指针传参
2.1.1传址调用(一级指针)
要想使一个函数影响函数外的内容,我们需要借助指针的帮助。
来看例子:
function(int* pa)
{
*pa = 6;
}
int main()
{
int x = 8;
int* px = &x;
function(px);
return 0;
}
这里px是实参,pa是形参
function函数调用前:实参px指向x
function函数调用:形参pa指向x
function函数调用(*pa = 6): pa指向内容改变 "x = 6"
function函数调用完成:形参销毁。
2.1.2传值调用(一级指针)
前面的例子看似好像打破了结论:”形参的改变不会影响实参“,实际上并不是这样。
来看例子:
function(int* pa)
{
pa = NULL;
}
int main()
{
int x = 8;
int* px = &x;
function(px);
return 0;
}
这里px是实参,pa是形参
function函数调用前:实参px指向x
function函数调用:形参pa指向x
function函数调用(pa = NULL):形参pa指向空(NULL)
function函数调用完成:形参销毁,实参并不改变(形参指向了NULL,而实参并没有改变依旧指向的x。
由此可以看出,我们借助指针进行传址操作只能改变当前指针指向的内容,并不能改变同级的实参 的值,所以并没打破 ”形参的改变不会影响实参“ 的准则。
2.2二级指针传参
理解了前面的内容我们就可以知道:要想通过函数改变主函数中一级指针的指向,就必须借助二级指针的帮助。
来看例子:
function(int** ppa)
{
**ppa = 6;
*ppa = NULL;
ppa = NULL;
}
int main()
{
int x = 8;
int* px = &x;
int** ppx = &px;
function(ppx);
return 0;
}
function函数调用前:实参ppx指向px,而px指向x。
function函数调用:形参ppa指向px。
function函数调用(**ppa = 6):主函数中x的值改变。
function函数调用(*ppa=NULL):主函数中的px指向NULL(这里就解决了前一举例中,我们传入一级指针时,无法改变一级实参指针的指向问题。看到这里你应该就能比较清楚的明白前面我提到的:要想通过函数改变主函数中一级指针的指向,就必须借助二级指针的帮助)
function函数调用(ppa=NULL):根据前面大家应该都知道了,由于我们只传进二级指针所以只有形参改变,主函数中的实参ppx不会有任何变化。
function函数调用完成:形参销毁,还是一样的,实参并不改变(形参指向了NULL,而实参并没有改变依旧指向的x)。
至此可以得出结论:在函数传参中形参的改变不会影响实参,如果想通过函数改变指针指向,我们必须传入比想改变的指针高一级的指针。
📝总结
通过函数改变指针指向的办法并不只有这一种办法,你也可以通过返回值(return)的形式来得到你想要的结果,但是相比于用返回值的方法,这样的写法有两个明显的好处:
1.使用函数简单(在调用函数时只需要放入就可改变,而不用特意去创建变量将结果拿回来)
2.能过改变多个指针指向(众所周知,函数可以有无数个形参,但是只能有一个返回值,所以用返回值的形式,我们即便改变了再多指针也只能返回一个,局限性太大,而传高一级指针的形式就不会存在这样的问题)
✨写在最后
在学习用c语言写链表时,经常不知道什么时候传一级指针什么时候传二级指针非常纠结,但后来一画图就彻底清楚了。因此将我的思考方式分享出来,帮助有同样困难的朋友更好的理解指针于函数传参的过程。
没有接触到的朋友也可以先看一看我的:数据结构学习笔记--单链表,里面有大量的二级指针传参,可以先接触试试,这也能让你知道传多级指针在具体案例中有什么用。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)