C语言:指针函数与函数指针

开场白:从字面上理解这两种概念

函数指针:是指向函数的指针变量(即本身是一种指针)

定义格式如下:

数据类型标志符 (*指针变量名) (参数)
void (*pf)(char *);//pf是指向函数的指针,void时函数返回值的类型,char*是函数参量的类型

指针函数:本质是函数,只不过返回值为某一类型的指针

定义格式如下:

返回类型标识符 *返回的指针名称 (形参)
void * pf(char *);//pf是返回一个指针的函数

===============================================================

重点理解函数指针:正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数,如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上一致的。

一般来说,想声明一个数据指针就必须说明它的指向数据的类型。所以在声明一个函数指针时,我们也要说明它指向的函数的类型,要指定函数的类型,就要说明函数的返回类型,以及函数的参量类型。比如对于下面的ToUpper函数: void ToUpper (char *); 函数ToUpper的类型就是:“具有char*类型的参量,返回类型是void的函数”,那么要想声明指向这一函数的指针变量pf可以这么做: void (*pf) (char *); 也就是直接用 (*pf) 来代替函数名即可(由于运算优先级的问题,括号一定要带上)

注意:在将函数指针指向函数时一定要保证类型的匹配

函数指针有两个用途:调用函数和做函数的参数

①调用函数

正如我们可以使用数据指针访问数据一样,我们也可以用函数指针访问(调用)函数,这里有两种逻辑上不一致的语法都可以实现调用函数(ANSI C把这这二者作为等价形式全部接受)

比如如下的代码:

void ToUpper (char *);
void ToLower(char *);
void (*pf)(char *);
char name[] = "Linden";
pf = ToUpper;
(*pf)(name);//把ToUpper作用于name,第一种语法
pf = ToLower;
pf(name);//把ToLower作用于name,第二种语法

以上两种调用方法等价


②做函数的参数

正如数据指针最常见的用法之一是作为函数的参数,函数指针最常见的用法也是作为函数的参数。例如:

void show (void (*fp)(char *),char *str);//void (*fp)(char *)为函数指针在此作为参数

在给定前面的声明的情况下,可以用下面的函数调用函数:

show (ToLower,name);//show()使用ToLower()函数:fp = ToLower
show (pf,name);//show()使用pf指向的函数:fp = pf

show函数时如何使用传递过来的函数指针的呢?它使用上面说过的语法fp( )或者(*fp)( )调用函数:

void show (void (*fp)(char *),char *str)
{
	(*fp)(str);//把所选函数作用于str,或者语法fp(str);也可以,上面解释过二者等价
	puts(str);//显示结果
}


指针函数的使用和一般函数的使用相同,但需注意返回值问题。对于一个返回值为指针的函数,不能返回auto型局部变量的地址,但可返回static型变量的地址。

这是因为auto型变量的生存周期很短,当函数返回时,auto型变量的内存空间将被释放,如果返回值是auto型变量,那么这个返回指针将无效,变成野指针。而static类型变量占用的内存空间则不会因为函数返回而被释放,不会出现野指针问题。

所以编写指针函数使要注意返回值。总体原则是:返回的指针对应的内存空间不会因函数返回则被释放掉。常用的返回指针有以下几种:

(1)      函数中动态分配内存空间(通过malloc等实现)的首地址;

(2)      静态变量(static)或全局变量所对应的变量的首地址;

(3)      通过指针形参所获得的实参的有效地址。


猜你喜欢

转载自blog.csdn.net/sinat_38486449/article/details/80024445