C 語言中的函式指標
Jinku Hu
2023年10月12日
本文將介紹如何在 C 語言中使用函式指標。
在 C 語言中使用 void (*func)()
符號來定義函式指標
函式指標是 C 語言程式設計中的又一個結構,它實現了動態函式呼叫、結中包含自己的方法等高階功能,類似於物件導向設計、型別通用程式設計等。需要注意的是,函式指標的宣告可能有複雜的語法,即 void(*func)(void)
記號宣告瞭指向 void
函式的指標,該函式不需要引數。雖然在下面的例子中,我們將取單一 int
引數的 printInt
函式的地址分配給 void(*func)(void)
型函式指標。一旦定義了名為 func
的函式指標,就可以用通常的函式呼叫符號 func(arg)
或用 dereferencing 運算子 (*func)(arg)
來呼叫它。
#include <stdio.h>
#include <stdlib.h>
void printInt(int x) { printf("printed from printInt: %d\n", x); }
int main() {
int input1 = 10233;
void (*func)(int) = printInt;
func(input1);
(*func)(input1);
exit(EXIT_SUCCESS);
}
輸出:
printed from printInt: 10233
printed from printDouble: 11.234000
另外,我們也可以使用 typedef
為函式指標定義一個新的型別別名,使程式碼更易讀。注意,不同的函式型別需要單獨的 typedef
語句。在下面的程式碼示例中,我們定義了一個沒有任何引數的 void 函式指標,儘管如此,printInt
和 printDouble
函式地址都儲存在型別為 FuncPtr
的變數中。需要注意的是,特定函式的地址可以通過顯式的&
運算子或函式名本身的隱式賦值來獲取,這在下一個例子中有所體現。
#include <stdio.h>
#include <stdlib.h>
typedef void (*FuncPtr)();
void printInt(int x) { printf("printed from printInt: %d\n", x); }
void printDouble(double x) { printf("printed from printDouble: %f\n", x); }
int main() {
int input1 = 10233;
double input2 = 11.234;
FuncPtr func1 = printInt;
FuncPtr func2 = printDouble;
func1(input1);
func2(input2);
exit(EXIT_SUCCESS);
}
輸出:
printed from printInt: 10233
printed from printDouble: 11.234000
使用函式指標陣列實現型別通用程式設計特性
像其他物件一樣,可以用括號 []
符號定義一個函式指標陣列。在執行時可以利用這個陣列方便地選擇和呼叫特定的函式。請注意,我們使用的是關鍵字 _Generic
,它是 switch
一樣的表示式,讓使用者根據控制表示式的型別評價來選擇具體的情況。因此,我們實現了下面的程式碼示例,根據 switch
條件中傳遞的變數型別,呼叫相應的 print
函式。請注意,enum
型別也被用來定義不同情況下的常量值。
#include <stdio.h>
#include <stdlib.h>
enum TYPE { INTEGER, DOUBLE, INVALID };
#define typename(x) \
_Generic((x), int: INTEGER, double: DOUBLE, default: INVALID)
typedef void (*FuncPtr)();
void printInt(int x) { printf("printed from printInt: %d\n", x); }
void printDouble(double x) { printf("printed from printDouble: %f\n", x); }
int main() {
int input1 = 10233;
double input2 = 11.234;
FuncPtr func_ptrs[] = {printInt, printDouble};
switch (typename(input1)) {
case INTEGER:
func_ptrs[INTEGER](input1);
break;
case DOUBLE:
func_ptrs[DOUBLE](input1);
break;
case INVALID:
printf("No corresponding type found!\n");
default:
break;
}
switch (typename(input2)) {
case INTEGER:
func_ptrs[INTEGER](input2);
break;
case DOUBLE:
func_ptrs[DOUBLE](input2);
break;
case INVALID:
printf("No corresponding type found!\n");
default:
break;
}
exit(EXIT_SUCCESS);
}
輸出:
printed from printInt: 10233
printed from printDouble: 11.234000
作者: Jinku Hu