C Function Pointer 基礎用法整理
這最近在看 jserv 大神的 linux 核心設計講座,因為之前比較少寫 c,所以對於 function pointer 只有一點概念但沒有真正寫過,所以趁這個機會寫個筆記來紀錄一下用法。
之後在學習的過程中如果遇到 function pointer 的應用也會一併整理在這篇文章中。
function pointer
function pointer 顧名思義就是指向某個 function 的 pointer,有了 function pointer 我們就可以實現把 function 當作參數,傳進一個 function 之中,或者更加彈性的設計我們的程式,減少多餘的 if/else, switch case。
我們先從一個簡單的 function pointer 宣告開始講起
int (*myFunc)(int, int);
上面就是一個基本的 function pointer 宣告
一個 function pointer 變數名稱為 myFunc,可以這麼解讀
- myFunc是一個指標指向一個- function- 該 function有兩個int的 parameters
- 該 function會回傳int
 
- 該 
假設今天我有個 function 宣告成以下這種形式
void parseFunc(float f1, int i1, char c1);
我們要怎麼宣告一個 pointer 去指向這個 function 呢?
void (*myFunc)(float, int, char);
解讀成
- myFunc是一個指標指向一個- function- 該 function有三個 parameters,分別要傳入- float
- int
- char
 
- 該 function會回傳void
 
- 該 
所以我們可以來驗證看看這個 function pointer 是否能真的呼叫 parseFunc 這個 function
#include <stdio.h>
void parseFunc(float f1, int i1, char c1) {
    printf("%f %d %c\n", f1, i1, c1);
}
int main() {
    parseFunc(0.87, 87, 'a');
    void (*myFunc)(float, int, char) = parseFunc;
    myFunc(0.87, 877, 'b');
    return 0;
}
注意
上面在宣告 function pointer 的時候
void (*myFunc)(float, int, char)
會注意到 *myFunc 會用括號包起來,這是不能省略的喔,省略的話就不是 function pointer 的宣告方法了。
省略的話會變成
void *myFunc(float, int, char);
這樣子 myFunc 就不是 function pointer 了,而是單純宣告一個 function
Jserv 上課的範例
簡單的例子看完就可以來看看 Jserv 在 你所不知道的C語言:指標篇 開頭所舉出來的範例
試試看能不能自己寫出該宣告怎麼解釋
void **(*d) (int &, char **(*)(char *, char **));
- d 是一個 function pointer, 該function有兩個parameters- 第一個 parameters: a reference to anint
- 第二個 parameters: 同樣也是一個function pointer- 該 function有兩個parameters- a pointer to a char
- a pointer to a pointer to a char
 
- a pointer to a 
- return a pointer to a pointer to a char
 
- 該 
 
- 第一個 
- return a pointer to a pointer to void
應用舉例
今天如果我想寫一個 calculate 的 function 該 function 有三個參數
- a
- b
- 加減乘除
傳入 a, b 之後再傳入要計算的動作,我們可以利用 function pointer 來取代 switch/case, 並增加可讀性
我們可以宣告成
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }
int div(int a, int b) { return a / b; }
int calculate(int a, int b, int (*cal)(int, int));
用這樣的宣告形式,就可以把我們實現好的加減乘除 function 當作參數傳入 calculate 當中
但是又有人會說 calculate 的第三個參數宣告還是有點複雜,有沒有辦法可以再讓可讀性增加呢?
這時候我們會習慣用 typedef 的關鍵字把常用的 function pointer 宣告取一個比較簡短的名稱
導入 typedef 之後我們可以寫成以下的形式
typedef int (*calc)(int, int);
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }
int div(int a, int b) { return a / b; }
int calculate(int a, int b, calc method) 
{
    return method(a, b);
}
這樣子我們在看 calculate 宣告的時候就會清楚的知道第三個參數要把指定的 method 傳進去。
完整的程式碼我放在 GitHub,可以把 code 載下來自己 run 一次,順便改改看寫法,觀察其中的不同。