函数指针和回调函数
1 函数指针
1.1 函数类型
通过什么来区分两个不同的函数?
一个函数在编译时被分配一个入口地址,这个地址就称为函数的指针,函数名代表函数的入口地址。
这一点和数组一样,因此我们可以用一个指针变量来存放这个入口地址,然后通过该指针变量调用函数。
函数三要素: 名称、参数、返回值。C语言中的函数有自己特定的类型。
//c语言中通过typedef为函数类型重命名:
typedef int f(int, int); // f 为函数类型
typedef void p(int); // p 为函数类型
注意:通过函数类型定义的变量是不能够直接执行,因为没有函数体。只能通过类型定义一个函数指针指向某一个具体函数,才能调用。
1.2 函数指针的定义方式
函数指针即指向函数的指针,它的定义方式有以下三种:
- 函数指针定义方式(先定义函数类型,根据类型定义指针变量);
- 先定义函数指针类型,根据类型定义指针变量;
- 直接定义函数指针变量;
#include <stdio.h>
void func(int a, char b)
{
printf("hello world\n");
}
int main()
{
// 1.通过typedef定义函数类型,再通过函数类型定义函数指针
// 定义了返回值为void类型, 形参一为int类型, 形参二为char类型的函数类型pFunc1
typedef void(pFunc1)(int, char);
pFunc1 *p = func;
p(1, 'a'); // 调用方法
// 2.通过typedef定义函数指针类型,再通过函数指针类型定义函数指针
// 定义了返回值为void类型, 形参一为int类型, 形参二为char类型的函数指针类型pFunc2
typedef void(*pFunc2)(int, char);
pFunc2 p2 = func;
p2(2, 'a');
// 3.直接定义函数指针
// 定义了返回值为void类型, 形参一为int类型, 形参二为char类型的函数指针pFunc3
void(*pFunc3)(int, char) = func;
pFunc3(3, 'a');
return 0;
}
2 回调函数
2.1 什么是回调函数
回调函数就是一个被 作为参数 传递 的函数。 即将一个函数传递到另一个函数中去调用,被传入的函数叫做回调函数。
再说通俗一点就是:其中函数A的某一个形参为函数指针,而函数B作为函数参数传递给函数A,在函数A中调用函数B,函数B就是回调函数。
#include <stdio.h>
void A(int a, void(*pFunc)()) // 形参二为一个返回值为void类型,无形参的函数指针(函数指针做函数参数)
{
pFunc(); // 在函数A中调用传入的函数
}
void B()
{
printf("hello world\n");
}
int main()
{
A(1, B); // 函数B作为函数参数传递给函数A,函数B就叫回调函数
return 0;
}
2.2 案例
2.2.1 提供一个函数,通过传入的回调函数,实现打印任意类型的数据
#include <stdio.h>
// 形参一:数据的地址;形参二:函数指针
void myPrint(void *p, void(pFunc)(void*))
{
pFunc(p);
}
void printInt(void *p) // 打印int类型的回调函数
{
int *pInt = (int*)p;
printf("%d\n", *pInt);
}
void printDouble(void *p) // 打印double类型的回调函数
{
double *pDouble = (double*)p;
printf("%f\n", *pDouble);
}
struct Person
{
char name[64];
int age;
};
void printPerson(void *p) // 打印自定义数据类型Person的回调函数
{
struct Person *pP = (struct Person*)p;
printf("姓名:%s, 年龄:%d\n", pP->name, pP->age);
}
int main()
{
int a = 10;
myPrint(&a, printInt);
double b = 10.1;
myPrint(&b, printDouble);
struct Person c{"aaa", 10};
myPrint(&c, printPerson);
return 0;
}
2.2.2 提供一个函数,通过传入回调函数,实现对任意类型的数组进行排序(选择排序,用户可以指定排序顺序)
#include <stdio.h>
// 形参一: 数组首地址; 形参二: 数组元素个数; 形参三: 排序规则(0-升序,非0-降序); 形参四: 函数指针
void mySort(void *pArray, int arrSize, int rules, void(*pFunc)(void*, int, int))
{
pFunc(pArray, arrSize, rules);
}
void intSort(void *p, int arrSize, int rules) // int类型数组排序的回调函数
{
int *pInt = (int*)p;
for (int ii = 0; ii < arrSize; ++ii)
{
int index = ii; // 记录下标值
for (int jj = ii+1; jj < arrSize; ++jj)
{
if (rules == 0)
{
if (pInt[index] > pInt[jj])
{
index = jj; // 记录真实的最小下标值
}
}
else
{
if (pInt[index] < pInt[jj])
{
index = jj; // 记录真实的最大的下标值
}
}
}
if (ii != index) // 判断index是否为最初的值,如果不是,说明需要交换元素
{
int tmp = pInt[ii];
pInt[ii] = pInt[index];
pInt[index] = tmp;
}
}
}
int main()
{
int arr[] = {5, 2, 3, 1, 0, 4};
mySort(arr, sizeof(arr)/sizeof(int), 0, intSort);
for (int ii = 0; ii < sizeof(arr)/sizeof(int); ++ii)
{
printf("%d\n", arr[ii]);
}
return 0;
}
364

被折叠的 条评论
为什么被折叠?



