回調函數用在哪個函數中? 提到回調函數,我也順手在網上翻了一下,我發現說的都比較詳細甚至于冗長了很多人的解說都比較類似,回想當初自己剛接觸的時候,我打算從一個非常簡單的角度用幾段話說完回調函數的使用和理解,今天小編就來說說關于回調函數用在哪個函數中?下面更多詳細答案一起來看看吧!
提到回調函數,我也順手在網上翻了一下,我發現說的都比較詳細甚至于冗長了。很多人的解說都比較類似,回想當初自己剛接觸的時候,我打算從一個非常簡單的角度用幾段話說完回調函數的使用和理解。
重點來了:什麼是回調函數?
在程序中把你的函數換成函數指針,用指針去替代你本該寫的函數名,這個被替代的函數就是回調函數。
結束!
用個簡單的代碼演示一下
//這裡是它的頭文件 Led.h
#ifndef __LED_H__
#define __LED_H__
void Led_On(void);
#endif
//這裡是一個文件 Led.c
//這是一個函數,假設它有個功能,就是點亮LED燈
void Led_On(void)
{
LED = TRUE;
}
這裡有另一個程序文件
//這裡是它的頭文件
#ifndef __SWITCH_H__
#define __SWITCH_H__
#include "Led.h" //方法一,引用LED頭文件
void Get_Switch_State(void);
#endif
//這裡是另一個文件 switch.c
//這裡有另一個函數,假設它檢測到某信号後需要點亮LED燈和處理一些事情;
extern void Led_On(void); //方法二,外部申明一下Led_On函數,如此才能跨函數調用
void Get_Switch_State(void)
{
if (Signel == TRUE)
Led_On(); //調用Led_On()函數,實現點亮LED功能
//.......
//do something
}
/* 要想能正常調用Led_On()函數,必須使用以上兩個方法之一
*/
上面就是一個普通的程序流程,流程中有個普通的函數調用,如果,我将Get_Switch_State()中的Led_On()更換成指向Led_On()函數的函數指針,那麼這時候Led_On就成了回調函數。
還是在另一個程序文件中
//這裡是它的頭文件
#ifndef __SWITCH_H__
#define __SWITCH_H__
#typedef void(*pFun)(void); //函數指針原型定義 重點一
void Get_Switch_State(void);
void CallBack_Reg(pFun cb);
#endif
//這裡是另一個文件 switch.c
//這裡有另一個函數,假設它檢測到某信号後需要點亮LED燈和處理一些事情;
pFun CallBack_Ptr; //定義一個函數指針 重點二
//回調函數的注冊函數CallBack_Reg()
void CallBack_Reg(pFun cb)
{
if (CallBack_Ptr == 0) //為函數指針賦值,當然它首先要沒有被賦值
CallBack_Ptr = cb;
}
void Get_Switch_State(void)
{
if (Signel == TRUE)
CallBack_Ptr(); //調用Led_On()函數的指針,實現點亮LED功能 重點三
//.......
//do something
}
/* 發現關鍵點沒有? switch.c 中再也沒有出現Led_On();那它如何實現調用?
答案是還需要在其它地方
比如說main函數中把Led_On()函數和CallBack_Ptr 這個指針綁定一下
*/
void main(void)
{
Gpio_Init();
Bsp_Init();
Timer_Init();
CallBack_Reg(Led_On); //重點四
while (1)
{
.......
}
}
從上面的代碼中可以明顯發現幾個特點
1.switch.c和.h中沒有出現Led_On()函數了。 Led_On()函數被函數指針CallBack_Ptr替代了。
2.switch.c和.h中沒有在引用文件Led.h了,實現了兩個c文件的解耦,使他們的關聯性降低了。
此時函數Led_On()就可以被稱作 回調函數 了。
講解完畢~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
好像還有點意猶未盡
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
總結一下,不要被回調函數的各種高深講解給弄暈了頭腦,它實際就是将你的函數用函數指針替代了,函數指針中存放的就是你的函數地址。
為了讓函數指針CallBack_Ptr能指向你Led_On()的地址,你需要做一個注冊功能函數CallBack_Reg(),将你要調用的函數地址傳遞給函數指針CallBack_Reg(Led_On);即CallBack_Ptr = Led_On。
這樣,在調用CallBack_Ptr 的時候就等于調用了Led_On。
完美解決。。
最後說明一下函數指針的定義
typedef void(pFun *)(void); //第一個void表示指向的函數返回參數為空,第二個void表示輸入參數為空
對比一下它要指向的函數 void Led_On(void) ; 數數void數量和位置理解了吧。
那如果有個函數帶有輸入參數怎麼辦呢?
聰明的你一定想到了
typedef void( pFun *)(unsigned char);
它可以指向的函數就如同 void Led_OnOff(unsigned char ) ;
使用
pFun CallBack_Ptr ; //定義函數指針
..........//注冊函數指針
CallBack_Ptr (InputDat); //使用函數指針,并傳遞值InputDat給了函數
.........
對于有返回值和多個輸入參數的函數就希望聰明的你舉一反三了!
完畢!
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!