- 概念
- 在C語言中,函式指標是一種特殊的指標型別,它指向的是函式而不是普通的資料變數。函式在記憶體中有其入口地址,函式指標就是用來儲存這個地址的變數。
- 函式指標的定義
- 函式指標的定義形式如下:
- 返回值型別 (*指標變數名)(引數型別列表);
- 例如,定義一個指向返回值為
int
,引數為int
和int
的函式的指標:int (*funcPtr)(int, int);
- 這裡
funcPtr
就是一個函式指標變數,它可以指向任何返回值為int
且有兩個int
型別引數的函式。
- 函式指標的定義形式如下:
- 函式指標的賦值與使用
- 賦值
- 可以將一個函式的地址賦給函式指標。例如:
int add(int a, int b) { return a + b; } int main() { int (*funcPtr)(int, int) = add; // 或者 int (*funcPtr)(int, int); funcPtr = add; return 0; }
- 可以將一個函式的地址賦給函式指標。例如:
- 使用函式指標呼叫函式
- 一旦函式指標被賦值,就可以透過函式指標來呼叫它所指向的函式。有兩種方式:
- 直接使用函式指標變數呼叫:
int add(int a, int b) { return a + b; } int main() { int (*funcPtr)(int, int) = add; int result = funcPtr(3, 5); printf("Result: %d\n", result); return 0; }
- 也可以將函式指標作為函式引數傳遞,在另一個函式中呼叫:
int add(int a, int b) { return a + b; } void callFunction(int (*funcPtr)(int, int), int num1, int num2) { int result = funcPtr(num1, num2); printf("Result: %d\n", result); } int main() { callFunction(add, 3, 5); return 0; }
- 直接使用函式指標變數呼叫:
- 一旦函式指標被賦值,就可以透過函式指標來呼叫它所指向的函式。有兩種方式:
- 賦值
- 函式指標陣列
- 可以定義函式指標陣列,這在需要根據不同情況呼叫不同函式時非常有用。例如:
int add(int a, int b) { return a + b; } int subtract(int a, int b) { return a - b; } int multiply(int a, int b) { return a * b; } int main() { int (*funcArray[])(int, int) = {add, subtract, multiply}; int result = funcArray[1](5, 3); printf("Result: %d\n", result); return 0; }
- 在這個例子中,
funcArray
是一個函式指標陣列,它包含了add
、subtract
和multiply
三個函式的指標。透過funcArray[1]
選擇subtract
函式的指標,然後呼叫subtract(5, 3)
得到結果。
- 可以定義函式指標陣列,這在需要根據不同情況呼叫不同函式時非常有用。例如:
- 函式指標作為函式返回值
- 函式可以返回函式指標。例如:
int add(int a, int b) { return a + b; } int subtract(int a, int b) { return a - b; } int (*selectFunction(int choice))(int, int) { if (choice == 0) { return add; } else { return subtract; } } int main() { int (*funcPtr)(int, int); funcPtr = selectFunction(1); int result = funcPtr(5, 3); printf("Result: %d\n", result); return 0; }
- 在這個例子中,
selectFunction
函式根據傳入的choice
引數返回add
函式或subtract
函式的指標,然後在main
函式中使用這個返回的函式指標呼叫相應的函式。
- 函式可以返回函式指標。例如:
- 用途
- 回撥函式
- 函式指標常用於實現回撥函式機制。例如,在一個排序演算法函式中,可以將一個比較函式的指標作為引數傳入。這樣使用者就可以根據自己的需求定義不同的比較函式,實現不同的排序邏輯。
- 事件驅動程式設計
- 在事件驅動的程式中,函式指標可以用來指向不同的事件處理函式。當某個事件發生時,透過函式指標呼叫相應的處理函式。
- 實現多型性(類似概念在C語言中的體現)
- 雖然C語言沒有像面嚮物件語言那樣的多型性,但函式指標可以在一定程度上實現類似的功能。例如,透過函式指標陣列,可以根據不同的情況呼叫不同的函式,類似於多型性中的根據物件型別呼叫不同的方法。
- 回撥函式
-
如何使用函式指標呼叫函式
- 直接呼叫
- 首先,定義一個函式指標並將其指向一個函式。例如,有一個函式
int add(int a, int b)
,定義函式指標並賦值如下:int (*funcPtr)(int, int) = add;
- 然後,可以使用函式指標直接呼叫函式:
int result = funcPtr(3, 5);
- 首先,定義一個函式指標並將其指向一個函式。例如,有一個函式
- 作為函式引數呼叫
- 定義一個函式,該函式接受一個函式指標作為引數。例如:
void callFunction(int (*funcPtr)(int, int), int num1, int num2) { int result = funcPtr(num1, num2); printf("Result: %d\n", result); }
- 在呼叫這個函式時,將實際的函式名作為引數傳入:
int add(int a, int b) { return a + b; } int main() { callFunction(add, 3, 5); return 0; }
- 定義一個函式,該函式接受一個函式指標作為引數。例如:
- 直接呼叫
-
如何透過函式指標訪問結構體成員(假設函式指標指向的函式操作結構體)
- 首先定義一個結構體和操作該結構體的函式。例如:
struct Point { int x; int y; }; int getX(struct Point *p) { return p->x; }
- 然後定義函式指標並賦值:
int (*funcPtr)(struct Point *); funcPtr = getX;
- 在使用函式指標時,傳入結構體指標引數:
struct Point p = {3, 5}; int result = funcPtr(&p);
- 這裡透過函式指標
funcPtr
呼叫getX
函式,getX
函式透過傳入的結構體指標p
訪問結構體成員x
。
- 首先定義一個結構體和操作該結構體的函式。例如:
-
函式指標與陣列指標的區別
- 指向的物件不同
- 函式指標:指向的是函式的入口地址。函式指標的定義形式為
返回值型別 (*指標變數名)(引數型別列表)
,例如int (*funcPtr)(int, int)
,它指向的是一個接受兩個int
引數並返回int
值的函式。 - 陣列指標:指向的是陣列。陣列指標的定義形式為
資料型別 (*指標變數名)[陣列大小]
,例如int (*arrPtr)[5]
,它指向的是一個包含5個int
元素的陣列。
- 函式指標:指向的是函式的入口地址。函式指標的定義形式為
- 指標運算不同
- 函式指標:函式指標的指標運算在標準C中沒有定義(因為函式在記憶體中的佈局不是像陣列那樣連續儲存元素的形式)。雖然在某些編譯器下可能有一些特定的實現,但從標準角度看,不應該對函式指標進行算術運算(如
++
、--
等)。 - 陣列指標:陣列指標可以進行指標運算。例如,如果
arrPtr
是一個指向包含5個int
元素陣列的指標,那麼arrPtr + 1
將指向記憶體中緊接著當前陣列的下一個包含5個int
元素的陣列(假設陣列在記憶體中是連續儲存的)。
- 函式指標:函式指標的指標運算在標準C中沒有定義(因為函式在記憶體中的佈局不是像陣列那樣連續儲存元素的形式)。雖然在某些編譯器下可能有一些特定的實現,但從標準角度看,不應該對函式指標進行算術運算(如
- 用途不同
- 函式指標:主要用於實現回撥函式、函式表(函式指標陣列)等功能,用於在不同的程式碼模組之間傳遞函式的呼叫關係,實現類似於多型的行為。例如,在排序演算法中傳入比較函式指標,以實現不同的排序邏輯。
- 陣列指標:用於處理多維陣列(特別是不規則的多維陣列)或者在函式引數傳遞中傳遞陣列的地址而不丟失陣列的維數資訊。例如,在處理矩陣運算時,使用陣列指標可以方便地遍歷矩陣。
- 指向的物件不同