函式指標
函式也住在記憶體裡——它們的機器碼坐落在某個位址,就跟資料一樣。函式指標(function pointer)是一個持有「函式位址」的指標,所以你可以把一個函式存進變數、當作引數傳遞、並呼叫指標當下所指名的那個函式。它把「這裡要執行哪段程式碼」變成一個你能在執行期選擇的值。
函式指標的型別把函式的簽章寫清楚:它接收什麼引數、回傳什麼,因為那正是正確呼叫它所需要的資訊。你藉由指名一個函式來設定它(函式名稱會退化成它的位址,很像陣列名稱),並藉由「寫出指標再接上引數」來透過它呼叫。最常見的用途是回呼(callback):你把一個函式指標交給某個通用的程序,它在適當時機回呼進你的程式碼——例如 qsort() 接收一個比較函式,並呼叫它來決定兩個元素的順序,於是同一個排序視你傳入的函式而能用於 int、字串或結構。函式指標表也能實作簡單的分派,依索引挑選一個動作。
誠實的提醒是:它的宣告語法出了名地醜——括號和星號擠在一起很彆扭——所以大多數真實程式碼會用 typedef 把它藏起來,讓其餘部分讀得乾淨。而且函式指標仍然是指標:透過一個空的或過期的函式指標呼叫是未定義行為,所以同樣的「信任之前先檢查」規矩依然適用。
int add(int a, int b) { return a + b; } int (*op)(int, int) = add; int r = op(2, 3); ——op 持有 add 的位址;呼叫 op(2, 3) 執行 add,r 是 5。之後改成 op = sub,同一個呼叫現在就改成相減。
int (*op)(int, int) 指名一個函式;op(2,3) 呼叫它當下所指的那個。
函式指標指向程式的唯讀程式碼區段,而非資料,所以它和物件指標是不同的東西——把兩者混用、或對函式指標做指標算術都沒有意義。真實程式碼中請用 typedef 包住宣告;裸寫的語法很容易讀錯。