【C语言回调函数】

C语言回调函数

在C语言中,是通过 函数指针 来实现函数回调的,具体可以分成4个步骤:
1、声明一个函数指针 p_A
2、定义一个函数 A
3、注册函数(其实就是把上面的函数地址赋值给函数指针 p_A = &A,俗称“挂钩子”)
4、通过函数指针调用函数(在需要的地方直接使用 p_A(), 和调用A() 效果一样)

1、什么是函数指针?

函数指针就跟指针变量差不多,不过它里面存储的不再是变量的地址,而是函数的入口地址。
以前我们调用函数是直接叫他的名字func();(偷偷告诉你,其实函数名字就是函数的入口地址的别名,相当于一个地址常量)
而现在我们可以把他的地址赋给函数指针,直接叫函数指针也能调用到这个函数。

①声明一个函数指针:
特别注意: 中间的括号不能省略

返回类型 (*函数指针)(参数列表)
例:uint8_t (*pAdd)(int a, int b)

int (*p)(int, int);   	// p是函数指针,可以指向返回类型为int,参数列表为(int, int)的函数
int *p(int, int)		// p是函数,返回类型为int指针,参数列表为(int, int)

看到了吧,少了个括号,意义完全不一样。

为了提高代码的重用率和可读性,还可以自定义一个函数指针类型,再用这个类型声明函数指针
一般在项目开发的时候,都是使用这种方法,

 int Add(int a, int b)					//函数定义
 {
 	return a + b;
 }
 typedef  int (*pAdd_t)(int, int);		//定义一个函数指针类型 pAdd_t
 pAdd_t  pAdd;							//用这个函数指针类型定义函数指针,更方便
 pAdd = Add;							//给函数指针赋值

②给函数指针赋值(用不用取址符 & 都可以,但要保证函数的返回值、参数列表要与函数指针一样才可以赋值)

“本来对函数名取地址是非法的,但很久以前有些编译器已经允许这样做,c/c++标准的制定者出于对象的概念已经有所发展的缘故,也承认了对函数名取地址的合法性。”

代码示例:

uint8_t (*pAdd)(int, int);	//声明函数指针
uint8_t Add(int a, int b) 	//函数定义
{
	return a + b;
}
//方法一
pAdd = Add;		//给函数指针赋值
//方法二
pAdd = &Add		//给函数指针赋值

//以后就可以这样调用,这三种调用方法都可以
Add(3, 2);
pAdd(3, 2);
(*pAdd)(3, 2);

2、再来说一下回调函数

【C语言回调函数】_第1张图片

在我们平时开发stm32或者其它单片机时,我们经常都会用到原厂提供的固件库函数,固件库函数中有非常多回调函数;回调函数是作为参数传递给另一个函数的函数。接受回调作为参数的函数预计会在某个时间点执行它。回调机制允许下层软件层调用上层软件层定义的函数。
一般来说,驱动层(下层)代码会释放注册函数 Callback_Register() 给用户,让用户把应用层(上层)函数注册成为回调函数。

这么说可能还是有点抽象,举个例子:(talk is cheap, show me the code)

**上层(应用层)代码:**

//回调函数(目前还不是,将会被注册为回调)
int Add(int a, int b)
{
	return (a + b);
}

//利用底层提供的API接口,进行注册回调函数
Callback_Register(Add);  //从此以后,Add就是回调函数了,(金箍戴上之后,你就再也不是个凡人,人世间的情欲不能再沾半点。。。。。)
========================================================================================================================
												简简单单分个层
========================================================================================================================
**下层(驱动层)代码:**

typedef  int(*pAdd_t)(int, int);		//先构建一个函数指针类型 pAdd_t
static  pAdd_t  pAdd;					//声明一个函数指针 pAdd

//这个是释放给用户注册回调用的
void Callback_Register(pAdd_t  callback)	//用户注册的时候,传入回调函数名字
{
	pAdd = callback;					//这里把回调函数赋值给函数指针,“挂钩子”
}

//底层调用
void Drive_Fun()
{
	pAdd(3, 2);						//因为之前用户已经把应用层函数注册为回调函数了,这里就通过函数指针调用到了回调函数
}

你可能感兴趣的:(c语言,开发语言,嵌入式)