函式指標
函式指標
定義
函式指標(也稱為子例程指標或過程指標)是指向函式的指標。與引用資料不同, 函式指標指向記憶體中的可執行程式碼。解引用函式指標時, 就如同引用函式一樣, 可以呼叫和傳遞引數。 這樣的呼叫就稱之為間接呼叫, 因為函式是通過變數間接呼叫的,而不是直接通過固定的識別符號或地址呼叫。
宣告
型別說明符 (*函式名) (引數)
比如
int (*p)(int x, inty);// 該函式指標對應的函式指標型別為 int (*) (int a, int b); void (*foo)(int);
初始化
- 方式一:對應的函式名賦值給變數
- 方式二:函式名前加 & 符號再賦值給變數
其實兩種方式是一樣的。 就如同陣列, 我們可以通過 &變數名 的方式取得陣列的地址, 也可以通過直接 變數名 取得地址。
舉例
double cm_to_inches(double cm) { return cm / 2.54; } double (*func1)(double) = cm_to_inches; // 或 double (*func1)(double) = &cm_to_inches;
c 語言中的示例
#include <stdio.h>/* for printf */ #include <string.h> /* for strchr */ double cm_to_inches(double cm) { return cm / 2.54; } // "strchr" is part of the C string handling (i.e., no need for declaration) // See https://en.wikipedia.org/wiki/C_string_handling#Functions int main(void) { double (*func1)(double) = cm_to_inches; char * (*func2)(const char *, int) = strchr; printf("%f %s", func1(15.0), func2("Wikipedia", 'p')); /* prints "5.905512 pedia" */ return 0; }
直接呼叫函式, 肯定是比使用函式指標方便, 容易。而函式指標在作為回撥函式時可以讓我們的程式設計變得更加簡單。
#include <math.h> #include <stdio.h> // Function taking a function pointer as an argument double compute_sum(double (*funcp)(double), double lo, double hi) { double sum = 0.0; // Add values returned by the pointed-to function '*funcp' int i; for(i = 0;i <= 100;i++) { // Use the function pointer 'funcp' to invoke the function double x = i / 100.0 * (hi - lo) + lo; double y = funcp(x); sum += y; } return sum / 101.0; } double square(double x) { return x * x; } int main(void) { doublesum; // Use standard library function 'sin()' as the pointed-to function sum = compute_sum(sin, 0.0, 1.0); printf("sum(sin): %g\n", sum); // Use standard library function 'cos()' as the pointed-to function sum = compute_sum(cos, 0.0, 1.0); printf("sum(cos): %g\n", sum); // Use user-defined function 'square()' as the pointed-to function sum = compute_sum(square, 0.0, 1.0); printf("sum(square): %g\n", sum); return 0; }
在以上的函式中, 使用函式指標在另一個函式(compute_sum
)中呼叫所傳入的函式(如 sin, con, square)。在該過程中,compute_sum
函式通過funcp
所傳入的函式, 實現compute_sum
函式達到不同的效果。
與typedef結合
在實際的使用過程中, 為了更易於閱讀, 更多的會結合typedef
方式進行。
#include <stdio.h>/* for printf */ #include <string.h> /* for strchr */ typedef double(*Func1)(double); typedef char* (*Func2)(const char *, int); double cm_to_inches(double cm) { return cm / 2.54; } int main(void) { Func1 func1 = cm_to_inches; Func2 func2 = strchr; printf("%f %s", func1(15.0), func2("Wikipedia", 'p')); /* prints "5.905512 pedia" */ return 0; }
函式指標陣列
其宣告如下
型別說明符 (*函式名[陣列長度]) (引數)
舉個例子
#include <stdio.h>/* for printf */ char * fun1(char * p) { printf("%s\n", p); return p; } char * fun2(char * p) { printf("%s\n", (p+1)); return p; } char * fun3(char * p) { printf("%s\n", (p+2)); return p; } int main() { char * (*pf[3])(char * p); pf[0] = fun1; pf[1] = &fun2; pf[2] = &fun3; pf[0]("fun1"); pf[1]("fun2"); pf[2]("fun3"); /** * 輸出: *fun1 *un2 *n3 */ return 0; }
或者使用函式指標宣告成陣列的形式。
#include <stdio.h>/* for printf */ typedef char * (*Func)(char * p); char * funa1(char * p) { printf("%s\n", p); return p; } char * funa2(char * p) { printf("%s\n", (p + 1)); return p; } char * funa3(char * p) { printf("%s\n", (p + 2)); return p; } int main() { Func pf[3]; pf[0] = funa1; pf[1] = funa2; pf[2] = funa3; pf[0]("Func0"); pf[1]("Func1"); pf[2]("Func2"); return 0; }
注意事項
- 賦給函式指標的函式應該和函式指標所指的函式原型(返回值, 引數一致)是一致的
- 函式指標沒有 ++ 和 -- 操作