C 語言中的函式指標
本文將介紹如何在 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
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn