1 前言 函數調用很好理解,即使剛學沒多久的朋友也知道函數調用是怎麼實現的,即調用一個已經封裝好的函數,實現某個特定的功能。 把一個或者多個功能通過函數的方式封裝起來,對外只提供一個簡單的函數介面,然後在其他地方調用即可 2 函數調用方式 函數調用難道還能怎麼調用?不就封裝好直接調用嗎??? 函數調 ...
1 前言
函數調用很好理解,即使剛學沒多久的朋友也知道函數調用是怎麼實現的,即調用一個已經封裝好的函數,實現某個特定的功能。
把一個或者多個功能通過函數的方式封裝起來,對外只提供一個簡單的函數介面,然後在其他地方調用即可
2 函數調用方式
函數調用難道還能怎麼調用?不就封裝好直接調用嗎???
函數調用方式分為兩種:直接調用和間接調用
2.1 直接調用
直接調用就是我們平常使用的方式,下麵的方式就屬於直接調用了。
int SumFun(int a, int b)
{
return a + b;
}
int main()
{
// 直接調用定義好的函數
int sum = SumFun(5, 6);
printf("sum=%d", sum);
return 0;
}
2.1 間接調用
間接調用在初學時很難使用到,這是通過函數指針的方式實現的。
函數指針本質是一個指針變數,是一個指向函數的指針(函數本身也是有地址的,指向的是函數入口);
而指針函數本質是一個函數,其返回值為指針。
函數指針的用法如下:
typedef int (*FunctionCB)(int, int);
int SumFun(int a, int b)
{
return a + b;
}
int main()
{
// 將定義好的函數賦值給函數指針
FunctionCB pfnSum = SumFun;
// 通過函數指針間接調用
int sum = pfnSum(5, 6);
printf("sum=%d", sum);
return 0;
}
3 什麼場景下使用
函數指針在軟體架構分層設計中十分重要,因為分層設計中有一個設計原則,那就是下層函數不能直接調用上層函數,那麼可以通過函數指針的方式實現;一般稱上層通過函數指針賦值給下層的函數為回調函數。
什麼情況會存在需要下層程式需要調用上層程式的呢?
比如串口數據接收,雖然可以通過查詢的方式接收,但是遠不及通過串口中斷的方式接收及時,當接收完成時,需要立即通知上層讀取數據進行處理,而不是等待上層程式查詢讀取。
如何實現呢?
比如硬體抽象層/驅動層中的串口模塊實現函數
/************* UART.c 文件 ****************/
static UartRecvCB sg_pfnUartRecv;
// 設置數據幀接收處理回調函數
void UART_SetRecvCallback(UartRecvCB pfnUartRecv)
{
sg_pfnUartRecv = pfnUartRecv;
}
void UART_Task(void)
{
if (RecvEnd)
{
// 數據一幀接收完成立即調用
if (sg_pfnUartRecv != NULL)
{
sg_pfnUartRecv(UartRecvBuf, UartRecvLength);
}
}
}
/************* UART.h 文件 ****************/
typedef void (*UartRecvCB)(const char *, int);
extern void UART_SetRecvCallback(UartRecvCB pfnUartRecv);
extern void UART_Task(void);
應用層代碼中實現回調函數,並調用下層函數。
// 回調函數:串口數據處理
void OnUartRecvProcess(const char *pBuf, int length)
{
// 處理串口數據
printf("Recv: %s", pBuf);
}
int main()
{
UART_SetRecvCallback(OnUartRecvProcess);
while(1)
{
if (TimeFlag)
{
UART_Task();
}
}
}
上述示例中通過函數指針的方式間接調用了應用層的函數,而且並不違背分層設計原則。
如果看代碼不能立即理解的話,可以嘗試通過下圖理解:
Callback 是一個函數指針類型的變數,通過函數 FML_TIME_Attach 拿到了應用層代碼函數 OnFunction(...) 的函數地址,之後在定時器中斷函數中根據觸發條件調用 Callback 即可,調用方式和直接調用 OnFunction(...) 沒有太大差異,只不過名字不一樣(可以理解成取了一個別名),為了保證系統運行安全,調用前要確保 Callback 不為 NULL,否則會引起程式異常。
本文來自博客園,作者:大橙子瘋,轉載請註明原文鏈接:https://www.cnblogs.com/const-zpc/p/16364419.html