【C语言】指针之函数指针(回调函数)
文章目录
一、函数指针的概念
函数指针的定义
若在程序中定义了一个函数,编译时,编译器会为函数代码分配一段存储空间,这段空间的起始地址(又称入口地址)称为这个函数的指针。
与普通变量相同,可以定义一个指针指向存放函数代码的存储空间的起始地址,这样的指针就是函数指针。
函数指针的定义格式如下:
返回值类型 (*变量名)(参数列表)
返回值类型是指针指向函数的返回值类型,*表示一个指针变量,参数列表是指针指向函数的形参列表。
【注释】因为*的优先级较高,所以要将*和变量名括起来
实例:
int func(int a,int b);//函数声明
int (*p) (int , int );//定义一个参数列表为两个int型的变量,返回值类型为int型的函数指针p
p=func;//函数指针p指向函数func的起始地址
二、函数指针的应用
(1)调用函数
使用函数指针调用对应函数,方法和使用函数名调用函数类似,只需将函数名替换成(*指针名)
调用函数指针p指向的函数
(*p)(3,5);
(2)将函数的地址作为函数参数传入其他函数。
将函数的地址传入其他参数,就可以在被调函数中使用实参函数。
将func的地址作为参数传入func2函数
void func2(int(*p)(int,int),int b,int c);
三、实例演示
#include <stdio.h>
void sum_row(int(*arr)[4], int raw, int* sum);//行求和函数声明
void sum_col(int(*arr)[4], int raw, int* sum);//列求和函数声明
//行求和函数定义
void sum_row(int(*arr)[4], int raw, int* sum) {
int i = 0;
*sum = 0;
for (; i < 4; i++) {
*sum += (*(*(arr + raw-1) + i));
}
}
//列求和函数定义
void sum_col(int(*arr)[4], int col, int* sum) {
int i = 0;
*sum = 0;
for (; i < 3; i++) {
*sum += (*(*(arr +i ) + (col-1)));
}
}
int main() {
int matrix[3][4];
int i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 4; j++) {
matrix[i][j] = i * 4 + j;
}
}
printf("输出初始矩阵:\n");
int(*p)[4];//定义数组指针p
p = matrix;
for (i = 0; i < 3; i++) {
for (j = 0; j < 4; j++) {
printf("%-5d", *(*(p + i) + j));
}
printf("\n");
}
int sum;
void (*q)(int(*arr)[4], int raw, int* sum);//定义函数指针
printf("计算第一行的和:\n");
q = sum_row;
(*q)(matrix, 1, &sum);//调用行求和函数
printf("sum=%d\n",sum);
printf("计算第一列的和:\n");
q = sum_col;
(*q)(matrix, 1, &sum);//调用列求和函数
printf("sum=%d\n", sum);
}
运行结果:

四、回调函数
程序通过参数把该函数的函数指针传递给了其它函数,在那个函数里面调用这个函数指针就相当于调用这个函数,这样的过程就叫回调,而被调用的函数就叫回调函数。
C语言回调函数的使用:
#include <iostream>
using namespace std;
//1.定义回调函数
void print(int n)
{
for (int i = 0; i < n; i++) {
cout << "hello world" << endl;
}
}
//2.定义回调函数原型(函数指针)
typedef void (*CallbackFun)(int);
//3.定义注册回调函数
void registCallback(CallbackFun callback,int n)
{
callback(n);
}
int main()
{
//4.将print函数指针作为参数传入注册函数registerCallback中调用callback,即执行了print函数。
registCallback(print, 10);
}
许多情况下,并不会再注册的时候调用回调函数,此时可以定义一个CallbackFun全局指针变量,在注册时将函数赋值给它,需要的时候调用它即可。
//1.定义回调函数
void print(int n)
{
for (int i = 0; i < n; i++) {
cout << "hello world" << endl;
}
}
//2.定义回调函数原型(函数指针)
typedef void (*CallbackFun)(int);
CallbackFun myCallback = nullptr;
//3.定义注册回调函数
void registCallback(CallbackFun callback)
{
myCallback=callback;
}
//4.定义调用回调函数的函数
void exec(int n)
{
myCallback(n);
}
int main()
{
//5.注册回调函数
registCallback(print);
exec(10);
}
C++回调函数的使用:
在C++中可以使用全局函数和静态函数作为回调函数。考虑到全局函数会破坏封装性,所以一般使用静态成员函数。即通过静态成员函数调用(访问)非静态成员函数的方法,以此来获取静态成员函数中的数据。