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