函数指针读书笔记
- 函數(shù)指針的定義格式
?
int f(int); int (*pf)(int) = &f;?
pf是一個函數(shù)指針,它能夠指向的是參數(shù)為int類型并且返回值為int類型的函數(shù)
2.? 也可以用typedef為函數(shù)指針類型取一個名字,然后再用該函數(shù)指針類型來定義指針變量:
???? typedef? <返回類型>? (*<函數(shù)指針類型名>)(<形參表>)。
?
typedef double (*PF)(double); PF pf;?
第一行是對一個函數(shù)指針進行了定義聲明,聲明了一個具有double返回值,并且參數(shù)是double類型的函數(shù)指針。以后就可以用PF來聲明其它的相同類型的函數(shù)指針。
- 函數(shù)指針的用途
- 轉(zhuǎn)換表(jump table)
- 作為參數(shù)傳遞給另一個函數(shù)
?
???? 作為參數(shù)傳遞給另一個函數(shù)?? 用法主要是回調(diào)函數(shù)(callback function),也就是用戶把一個函數(shù)指針作為參數(shù)傳遞給其它函數(shù),后者將“回調(diào)”用戶的函數(shù)。一個很常用的例子就是c函數(shù)庫的qsort函數(shù), qsort并不知道進行比較的值的類型,這是我們就可以傳入一個比較函數(shù)的函數(shù)指針,對于不同類型的比較,我們可以讓這個函數(shù)指針綁定到不同的函數(shù)上。這里就不詳細說了。
轉(zhuǎn)換表 對于用戶的不同輸入,我們要調(diào)用不同的函數(shù)實現(xiàn)不同的功能,這時候也許我們可以用switch語句來實現(xiàn)。但是當每次我要增加一些操作的時候,就必須修改switch,也就是修改main函數(shù)里面的代碼,這樣是非常不方便的。那我們就可以用跳轉(zhuǎn)表來實現(xiàn),跳轉(zhuǎn)表其實就是一函數(shù)指針數(shù)組。一般的用法如下[1]:
代碼實現(xiàn)如下:
#include <stdio.h>typedef void (*PF)(void);struct jump_table{char ch;PF pf; };void pf_a(void) { printf("CALL pf_a\n"); } void pf_b(void) { printf("CALL pf_b\n"); } void pf_w(void) { printf("CALL pf_w\n"); }struct jump_table table[100] = { //跳轉(zhuǎn)表{'a',pf_a},{'b',pf_b},{'w',pf_w},{0,NULL} };int main() {char ch;int i;while( (ch = getchar()) != 'x'){i = 0;while ((table[i].ch != 0)){if (ch == table[i].ch){ table[i].pf();break;}i++;}} }2013/10/16 22:33我們可以看到用戶輸入的key值是不連續(xù)的,所以我們必須每次都掃描一遍數(shù)組,同時我們在定義數(shù)組的時候要設置結束標志,這樣能方便判斷結束。
但是如果用戶輸入的是從零開始的連續(xù)整數(shù),或者是一些諸如連續(xù)字符a-z之類的,那么我們就可以直接跳轉(zhuǎn)到相應的項,而不需掃描數(shù)組。比如我們在做計算器的時候,我們把ADD定義為0,SUB定義為1....[2],那么就可以如下的定義:
double add(double, double); double sub(double, double); double mul(double, double); double div(double, double); ....double (*oper_func[])(double,double) = {add,sub,mul,div,..... };
然后通過下面來調(diào)用相應的操作函數(shù),oper為輸入的值:
result = oper_func[oper](op1, op2);oper_func從數(shù)組中選擇正確的函數(shù)指針,而函數(shù)調(diào)用操作符將執(zhí)行這個函數(shù)。當然,我們這里還需要的注意的是數(shù)組越界問題,為了保證所使用的下標位于合法的范圍內(nèi),在一開始的時候我們可以先檢查下標的合法性,然后再進行調(diào)用操作。
- ?參考資料
- [1] 我們老師上課的課件,具體解釋權歸老師所以;
- ????? [2] 《C和指針》
?
復雜函數(shù)指針的應用
來看下下面這個代碼:
void (* pf(void (*fun)()))()咋第一眼看上去有點頭暈呢!那么多括號,那么多嵌套。莫急莫急!我們來把它細分一下,首先看 void (*fun)(),這就是我們前面看到的函數(shù)指針,這個沒問題。然后再看看
pf(void (*fun)()),pf不也是一個函數(shù)嘛,只不過它的參數(shù)是一個函數(shù)指針罷了。那么如果我們令pf(void (*fun)())為X,那么那一整個式子可以表示成:void(*X)(),這就是函數(shù)指針的定義。說明X又是一個函數(shù)指針,也就是說函數(shù)pf的返回值又是一個函數(shù)指針。這樣就都清楚啦,再來屢一下:pf這樣一個函數(shù):接受參數(shù)為函數(shù)指針,而且pf的返回值也是個參數(shù)為void返回值為void的函數(shù)指針。
而且我們還可以用下面這兩個定義來表示上面這個函數(shù)定義,這樣看起來就明了多了:
?
typedef void (*PF)(); PF pf(PF fun); typedef void PF(); PF *pf(PF *fun);?從下面這個定義方式,我們就可以很明確的看到pf函數(shù)的參數(shù)是一個PF*類型,返回值也是一個PF*類型的函數(shù)。
?
下面用一個程序來看看這個應用的例子:
?
#include <stdio.h>void fun_a(int a,int b) {printf("This is function A.\n"); }void fun_b(int a) {printf("This is function B.\n"); }void (*pf(void (*fun)(int,int)))(int) {void (*p)(int);printf("This is function pf.\n");fun(1,1);p = fun_b;return p; }int main() {pf(fun_a)(1);return 0; }輸出結果是:
?
?參考資料:
http://bbs.csdn.net/topics/30344321
?
轉(zhuǎn)載于:https://www.cnblogs.com/Jason-Damon/p/3373101.html
總結
- 上一篇: fatal: remote origin
- 下一篇: 买了两本“博客园开发者征途”系列的书