我们了解了指针和数组的关系,以及一些特殊的指针之后,再来看一下指针和函数的关系
1 指针作为函数的参数
c语言当中函数的参数,是"值传递",也就是说把实参的值,赋值给形参,我们看一个例子
#include
这是一个交换两个变量的值的程序
![07396345efaf40fe5d1606436eedbd2c.png](https://i-blog.csdnimg.cn/blog_migrate/439730d9ef349cba191499d5f4924f64.png)
这样就完成了两个变量指的交换
![7e473345a316b86fe6447aaa28f353c6.png](https://i-blog.csdnimg.cn/blog_migrate/fa162742d049c79dd12a8776820a8fef.png)
如果我们使用函数来完成这个过程
#include
![baba3e08d15f294dd5aba7edabea8d64.png](https://i-blog.csdnimg.cn/blog_migrate/cc8314d416a1083d716a127ed61f4e4c.png)
发现交换并没有成功
这里的原因就是,在使用函数的时候,我们传递给函数的参数,并不是变量本身,而是变量的值,也就是说,swap(a,b)的调用,实际上执行的是swap(10,20),无论函数执行的结果如何,都不会影响到主函数当中的a,b原来的值
为了解决这个问题,我们可以把两个指针作为参数,向函数传递两个变量的地址
#include
函数的参数会接受两个变量的地址,在函数内部对地址保存的值进行操作,这样就完成了对主函数中变量值的修改
![4d45f18e75a251ded8cb7302fab30052.png](https://i-blog.csdnimg.cn/blog_migrate/12a8033c5542725fd297d753eda4b8cd.png)
也就是说,如果我们需要通过函数去修改变量的值的时候,可以把形参定义为指针,把变量的地址当作实参
比如我们需要利用函数改变变量的值,会有两种做法,第一种是利用函数返回值
#include
a = change(a),就是把a的值传递到函数,得到的返回值在重新赋值给a,从而改变了a的值
![65af72e55514555cfd4e7dcdf5bc4aef.png](https://i-blog.csdnimg.cn/blog_migrate/69251d0e8597694f59ca48c25590d675.png)
也可以利用指针作为函数参数来实现
#include
change(&a),直接传入变量a的地址,在函数内部修改地址保存的值
![c8d6595bd51a0775b5b075c4a4c6d2a7.png](https://i-blog.csdnimg.cn/blog_migrate/6d37562294b71622ad935274bb550f9c.png)
2 指针作为函数的返回值
返回值是指针的函数我们一般叫做指针函数
如果传入的参数是指针,经过函数内部的一系列处理,再将这个指针返回原来的位置,那么就可以声明函数的返回值是指针类型
一般字符串和数组的变量保存的数据都可以看作是变量的地址,所以返回值是指针的函数一般都代表返回值是数组或者字符串
比如我们设计一个函数,参数是两个字符串,返回值是两个字符串当中比较长的那一个
#include
![a21c8bd97f3e1342cd32c4e4089cec63.png](https://i-blog.csdnimg.cn/blog_migrate/3f93ced1ff4943bbffe7f3bcb32e493e.png)
当函数返回一个指针的时候,一定要注意,就是函数内的局部变量会在函数执行之后被销毁,所以尽量不要把函数的局部变量地址作为函数的返回值
#include
这样程序会出错
3 指向函数的指针
在程序里面,如果不调用函数,只是用函数名的化,函数名也可以看作是函数所在的内存代码区的地址
#include
![5dc602b6b4fe4ecfad53235669843815.png](https://i-blog.csdnimg.cn/blog_migrate/7f4b24dd8ed3192895a376d6429bd52e.png)
这里使用fun代表了函数的地址
注意区分fun和fun()的区别,前者是函数本身,后者是函数的调用
我们可以定义一个指针去指向函数的地址,这就是函数指针
声明一个函数指针,需要指明指针指向的函数的返回值类型,和参数类型
#include
这里定义了一个函数,int fun(int a,int b),用来计算两个整数的值
在主函数中定义了一个指针 p 指向了这个函数
根据声明的运算符优先级
![fb8c0aaf14ce477a71e55b85088ec3c7.png](https://i-blog.csdnimg.cn/blog_migrate/fc3be712f3e6aa53027fc1f6816ce07f.png)
调用的时候 *p 表示从地址找到对应的函数fun,(*p)(1,2)就相当于函数的调用fun(1,2),其实和数组类似,直接使用p()也是可以的
![cf36cf0531746cb96bddfa82510cff5e.png](https://i-blog.csdnimg.cn/blog_migrate/83c046b6dd1a58231da8a577261e932d.png)
利用函数指针我们就可以把函数也当作一种数据来处理,可以把函数保存到数组中,也可以把函数当作另外一个函数的参数
#include
这里的三个函数 add,sub,mul的参数和返回值类型都相同,可以认为是相同类型的函数
函数use的参数包含一个函数指针,在调用的时候传入一个函数,这里的灵活性就在于,use函数可以根据传入的参数不同实现不同的功能
![4cf362fe7fff5600918fc3011db5ff99.png](https://i-blog.csdnimg.cn/blog_migrate/c80fa6ba4d882e53a456e5199fb7331f.png)
如果学习过Javascript的回调函数,或者java,c++,python当中的lambda表达式,那么对这个内容就会感到非常的熟悉