関数ポインタ

関数ポインタは関数を指すポインタ変数です。

通常、私たちが言うポインタ変数は整数型、文字型、配列などの変数を指しますが、関数ポインタは関数を指します。

関数ポインタは通常の関数と同じように、関数の呼び出しや引数の受け渡しに使用できます。

関数ポインタ型の宣言:

typedef int (*fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针类型

例

次の例では、関数 max を指す関数ポインタ変数 p を宣言しています。

例

#include <stdio.h> int max(int x, int y) { return x > y ? x : y; } int main(void) { /*p は関数ポインタです*/ int (* p)(int, int) = & max; // & は省略可能 int a, b, c, d; printf("3つの数字を入力してください:"); scanf("%d %d %d", & a, & b, & c); /*関数を直接呼び出すのと同等で、d = max(max(a, b), c) です。*/ d = p(p(a, b), c); printf("最大の数字は: %d\n", d); return 0; }

コンパイルして実行すると、出力結果は次のようになります:

请输入三个数字:1 2 3
最大的数字是: 3

コールバック関数

関数ポインタをある関数のパラメータとして使う

関数ポインタ変数はある関数のパラメータとして使用できます。コールバック関数とは、関数ポインタを介して呼び出される関数のことです。

簡単に言うと、コールバック関数は、他の関数が実行されるときに呼び出される、あなたが実装した関数です。

以下は知乎(Zhihu)の著者・常溪玲氏による解説です:

あなたが店に買い物に行き、ちょうど欲しい商品が在庫切れだったため、店員に電話番号を預けました。数日後、店に在庫が入ると、店員があなたに電話をかけ、あなたはその電話を受けて店に商品を取りに行きました。この例では、あなたの電話番号はコールバック関数、店員に電話番号を預けることはコールバック関数の登録、店に在庫が入ることはコールバックに関連するイベントの発生、店員が電話をかけることはコールバック関数の呼び出し、店に商品を取りに行くことはコールバックイベントへの応答と呼ばれます。

例

例の中でpopulate_array()この関数は3つのパラメータを定義しており、その3番目のパラメータは関数ポインタで、この関数を介して配列の値を設定します。

例ではコールバック関数を定義していますgetNextRandomValue()、これはランダムな値を返し、関数ポインタとして渡されますpopulate_array()関数。

populate_array()呼び出し、10回コールバック関数を呼び出し、コールバック関数の戻り値を配列に代入します。

例

#include <stdlib.h> #include <stdio.h> void populate_array(int *array, size_t arraySize, int (*getNextValue)(void)) { for (size_t i=0; i<arraySize; i++) array[i] = getNextValue(); } // ランダム値を取得 int getNextRandomValue(void) { return rand(); } int main(void) { int myarray[10]; /*getNextRandomValue に括弧を付けることはできません。付けないとコンパイルできません。括弧を付けると、このパラメータを渡すときに int が渡されることになり、関数ポインタではなくなるからです。*/ populate_array(myarray, 10, getNextRandomValue); for(int i = 0; i < 10; i++) { printf("%d ", myarray[i]); } printf("\n"); return 0; }

コンパイルして実行すると、出力結果は次のようになります:

16807 282475249 1622650073 984943658 1144108930 470211272 101027544 1457850878 1458777923 2007237709 
その他の拡張