指针函数
1.含义
1)指针函数指的是一个函数返回值为指针类型的函数,本质就是个函数。
2)函数指针指的是指向函数的指针变量,本质是一个指针变量。
2.声明和定义
1)指针函数声明
类型关键字 *函数名(参数列表)
例:
int *fun(int a,int b);
2)函数指针声明
类型关键字 (*函数名)(参数列表)
例:
int (*fun)(int a,int b);
注意:函数指针在使用时与普通指针一样,需要初始化指向有效地址才能使用,函数指针则指向函数实体的地址,即是函数名称。
对于函数指针,也可以结合“typedef”关键字使用,这样即可自定义一类新的的函数指针类型,可以用该类型声明和定义同一类的函数指针。
typedef 类型关键字(函数名 *)(函数列表)
例:
typedef int (*fun)(int a,int b);
此时“fun”作为自定义的函数指针,可用来声明或者定义同一类型的函数指针,如“fun max;” 、“fun min;’”。
3.使用
1)指针函数使用
指针函数的使用和一般函数的使用相同,只是返回值是一个指针值,即地址。对于指针函数的返回值,需要注意如下几点。
a.不能返回从栈上分配的内存地址,如局部变量,因为函数结束时,即释放栈内存,此时返回栈上内存地址,相当于野指针。
b.可以返回静态变量(static)、全局变量的地址、从堆上手动分配(malloc/new)的内存地址、通过指针形参所获得的实参的有效地址。
c.返回从堆上手动分配的内存时,注意及时释放(free/delete),否则导致内存泄漏,一般不建议使用这种方式,降低程序的可读性和可靠性。
例:
返回static 变量地址
int *fun(void)
{
static int a;
return &a;
}
返回全局变量地址
int a;
int *fun(void)
{
return &a;
}
返回从堆上分配的地址(慎用!)
int *fun(void)
{
int *a = malloc(sizeof(int));
return a; //返回该地址后,需手动释放该指针指向的内存。
}
返回通过指针形参所获得的实参的有效地址
int *fun(int *buff)
{
return buff;
}
2)函数指针使用
在使用函数指针前,必须对函数指针进行初始化指向函数实体。
实例:通过函数指针比较两个数的大小。
a.声明函数指针
int (*fun)(int a,int b);
b.定义函数实体
在定义函数实体时,必须保证类型与函数指针一致,包括返回值,参数类型、个数等。
int max(int a,int b)
{
if(a == b)
return 0;
return(a > b ? a :b); //比较两个整型数大小,并返回较大值
}
int min(int a,int b)
{
if(a == b)
return 0;
return(a < b ? a :b); //比较两个整型数大小,并返回较小值
}
c.赋值
如果需返回两数中较大的值,则初始化指针指向max函数即:
fun = max;或者fun = &max;
否则指向min函数:
fun = min;或者fun = &min;
注意:指针在指向变量时,必须使用取值符号“&”获取变量地址,而对于函数,则不是必须的,因为函数名称则表示该函数的地址。
d.使用
调用时有两种方式:
a)函数指针名称(参数列表);即fun(a,b);
b)(*函数指针名称)(参数列表);即(*fun)(a,b);
对于第二种方式比较直观理解,表明是通过函数指针调用改函数的。
int x;
fun = max;
x = (*fun)(4,5);//x值为5 或者 x = fun(4,5)
fun = min;
x = (*fun)(4,5);//x值为4 或者 x = fun(4,5)
函数指针的使用场景
函数指针的常见用法就是把函数指针作为参数传递给函数。一个函数通过由运行时决定的指针来调用另一个函数的行为叫做回调(callback)。用户将一个函数指针作为参数传递给其它函数,后者将“回调”用户的函数。这样就可实现通过同一接口实现不同的执行效果(类似C++中的多态性)。
另外在驱动函数分层,通用函数接口等,也常见使用函数指针的方式。