C語言 函式指標

西北野狼發表於2024-10-02
  1. 概念
    • 在C語言中,函式指標是一種特殊的指標型別,它指向的是函式而不是普通的資料變數。函式在記憶體中有其入口地址,函式指標就是用來儲存這個地址的變數。
  2. 函式指標的定義
    • 函式指標的定義形式如下:
      • 返回值型別 (*指標變數名)(引數型別列表);
      • 例如,定義一個指向返回值為int,引數為intint的函式的指標:
        int (*funcPtr)(int, int);
        
      • 這裡funcPtr就是一個函式指標變數,它可以指向任何返回值為int且有兩個int型別引數的函式。
  3. 函式指標的賦值與使用
    • 賦值
      • 可以將一個函式的地址賦給函式指標。例如:
        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;
          }
          
  4. 函式指標陣列
    • 可以定義函式指標陣列,這在需要根據不同情況呼叫不同函式時非常有用。例如:
      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是一個函式指標陣列,它包含了addsubtractmultiply三個函式的指標。透過funcArray[1]選擇subtract函式的指標,然後呼叫subtract(5, 3)得到結果。
  5. 函式指標作為函式返回值
    • 函式可以返回函式指標。例如:
      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函式中使用這個返回的函式指標呼叫相應的函式。
  6. 用途
    • 回撥函式
      • 函式指標常用於實現回撥函式機制。例如,在一個排序演算法函式中,可以將一個比較函式的指標作為引數傳入。這樣使用者就可以根據自己的需求定義不同的比較函式,實現不同的排序邏輯。
    • 事件驅動程式設計
      • 在事件驅動的程式中,函式指標可以用來指向不同的事件處理函式。當某個事件發生時,透過函式指標呼叫相應的處理函式。
    • 實現多型性(類似概念在C語言中的體現)
      • 雖然C語言沒有像面嚮物件語言那樣的多型性,但函式指標可以在一定程度上實現類似的功能。例如,透過函式指標陣列,可以根據不同的情況呼叫不同的函式,類似於多型性中的根據物件型別呼叫不同的方法。

  1. 如何使用函式指標呼叫函式

    • 直接呼叫
      • 首先,定義一個函式指標並將其指向一個函式。例如,有一個函式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;
        }
        
  2. 如何透過函式指標訪問結構體成員(假設函式指標指向的函式操作結構體)

    • 首先定義一個結構體和操作該結構體的函式。例如:
      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
  3. 函式指標與陣列指標的區別

    • 指向的物件不同
      • 函式指標:指向的是函式的入口地址。函式指標的定義形式為返回值型別 (*指標變數名)(引數型別列表),例如int (*funcPtr)(int, int),它指向的是一個接受兩個int引數並返回int值的函式。
      • 陣列指標:指向的是陣列。陣列指標的定義形式為資料型別 (*指標變數名)[陣列大小],例如int (*arrPtr)[5],它指向的是一個包含5個int元素的陣列。
    • 指標運算不同
      • 函式指標:函式指標的指標運算在標準C中沒有定義(因為函式在記憶體中的佈局不是像陣列那樣連續儲存元素的形式)。雖然在某些編譯器下可能有一些特定的實現,但從標準角度看,不應該對函式指標進行算術運算(如++--等)。
      • 陣列指標:陣列指標可以進行指標運算。例如,如果arrPtr是一個指向包含5個int元素陣列的指標,那麼arrPtr + 1將指向記憶體中緊接著當前陣列的下一個包含5個int元素的陣列(假設陣列在記憶體中是連續儲存的)。
    • 用途不同
      • 函式指標:主要用於實現回撥函式、函式表(函式指標陣列)等功能,用於在不同的程式碼模組之間傳遞函式的呼叫關係,實現類似於多型的行為。例如,在排序演算法中傳入比較函式指標,以實現不同的排序邏輯。
      • 陣列指標:用於處理多維陣列(特別是不規則的多維陣列)或者在函式引數傳遞中傳遞陣列的地址而不丟失陣列的維數資訊。例如,在處理矩陣運算時,使用陣列指標可以方便地遍歷矩陣。

相關文章