C 語言中的函式指標

Jinku Hu 2023年10月12日
  1. 在 C 語言中使用 void (*func)() 符號來定義函式指標
  2. 使用函式指標陣列實現型別通用程式設計特性
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 函式指標,儘管如此,printIntprintDouble 函式地址都儲存在型別為 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
Jinku Hu avatar Jinku Hu avatar

DelftStack.com 創辦人。Jinku 在機器人和汽車行業工作了8多年。他在自動測試、遠端測試及從耐久性測試中創建報告時磨練了自己的程式設計技能。他擁有電氣/ 電子工程背景,但他也擴展了自己的興趣到嵌入式電子、嵌入式程式設計以及前端和後端程式設計。

LinkedIn Facebook

相關文章 - C Pointer