摘要:
在学习C语言时,一个比较容易混淆的概念就是函数指针、指针函数、返回值为指针的函数。本文将对这三个概念进行区分。指针函数就是返回值为指针的函数,两个本质上是同一事物,只是叫法不同。函数指针就是一个指向函数的指针,本质上是一个指针,只是这个指针指向的对象是函数,而不是一般意义上的存储对象。
正文:
指针函数
指针函数就是返回指针值的函数,本质是一个函数。所以指针函数等价于“返回值为指针的函数”。
定义
指针函数的定义格式如下:函数类型 *函数名([参数列表])
当然,也可以让指针标志*与函数类型紧贴在一起,与函数名分开,其含义一致,格式如下:函数类型* 函数名([参数列表])
相比上一种,这种方式更能表示这是一个指针函数。在将指针函数与函数指针区分时,也可以通过“指针标志*能否和函数名分离”来判断这个一个指针函数,还是一个函数指针。
返回值问题
指针函数的使用和一般函数的使用相同,但需注意返回值问题。对于一个返回值为指针的函数,不能返回auto型局部变量的地址,但可返回static型变量的地址。
这是因为auto型变量的生存周期很短,当函数返回时,auto型变量的内存空间将被释放,如果返回值是auto型变量,那么这个返回指针将无效,变成野指针。而static类型变量占用的内存空间则不会因为函数返回而被释放,不会出现野指针问题。
所以编写指针函数使要注意返回值。总体原则是:返回的指针对应的内存空间不会因函数返回则被释放掉。常用的返回指针有以下几种:
(1)函数中动态分配内存空间(通过malloc等实现)的首地址;
(2)静态变量(static)或全局变量所对应的变量的首地址;
(3)通过指针形参所获得的实参的有效地址。
函数指针
函数指针就是一个指向函数的指针。每个函数在编译时,会被分配一个入口地址,一般用函数名来表示,这个地址就是该函数的指针。
定义
函数指针的定义格式如下:函数类型 (*指针变量) ([参数列表])
在形式上,函数指针的特征是使用一个括号包裹指针标志和指针变量,将括号移除,函数指针就变成指针函数。
之所以容易混淆指针函数和函数指针,是因为指针函数的形式如一般指针变量类型,如:int *x、int *y()、int(*z)()
这里x和z表示一个指针,而y则表示一个函数,所以要注意区分指向变量的指针和指向函数的指针的形式区别。
赋值
函数指针的赋值操作:
使用函数名给指向函数的指针变量赋值。其赋值的一般格式如下:函数指针 = [ &] 函数名;
其中,函数名后不能带括号和参数,函数名前的&是可选,建议不要使用。
调用
函数指针调用格式:函数指针变量([实参列表]); 或(*函数指针变量)([实参列表]);
推荐第二种用法。这种方法可以很好的表明这是一个函数。而第一种方法则很容易造成误导。
之所以容忍一种调用方法是因为ANSI C 委员会决定容许这种普通函数调用句法。这是因为编译器知道它是一个指向函数的指针,并且它还知道在该环境下所能做的惟一的一件事就是调用函数,因此这里没有任何模糊不清的表达。
使用场景
函数指针的常见用途就是把函数指针作为参数传递给函数。
一个函数通过由运行时决定的指针来调用另一个函数的行为叫做回调(callback)。用户将一个函数指针作为参数传递给其它函数,后者将“回调”用户的函数。这样就可实现通过同一接口实现对不同类型数据、不同功能的处理。