関数ポインタとは 「int* foo()」といったもの返り値がポインタの関数ではありません。定義したポインタに関数を入れるという、大胆な方法です。使用例を見た方が早いので、下の例を見てみましょう。
#include <stdio.h> int sub(){ printf("A\n"); return 0; } int main(){ int (*func)(); /* 関数ポインタの宣言 */ func = sub; /* funcにsubをセットする */ func(); /* funcを実行するとsubが実行される */ return 0; }
関数ポインタ宣言時の書き方に注意してください。ポインタをカッコで囲むところがポイントです。
型 (*関数ポインタ名)(引数...)
関数ポインタには型、引数の一致する任意の関数をセットできます。セットするときは、関数名をそのまま指定すればOKです。
上の例では、funcにsubがセットされているので、funcを呼ぶと、subが呼ばれます。
これだけだと、使い道がよくわからないので、もう少し例を見てみましょう。
入力した値によって、呼び出す関数を変えるプログラムを作ります。まずは、関数ポインタを使わずに。
#include <stdio.h> void func1(){ printf("A\n"); } void func2(){ printf("B\n"); } void func3(){ printf("C\n"); } int main(){ char c[10]; fgets(c, sizeof(c), stdin); switch(c[0]){ case '1': func1(); break; case '2': func2(); break; case '3': func3(); break; default: break; } return 0; }
関数ポインタを使うとこの様にかけます。
#include <stdio.h> void func1(){ printf("A\n"); } void func2(){ printf("B\n"); } void func3(){ printf("C\n"); } int main(){ struct tagX { char key; void (*func)(); } stX[] = { {'1', func1}, {'2', func2}, {'3', func3} }; char c[10]; int i; fgets(c, sizeof(c), stdin); for(i = 0; i < sizeof(stX)/sizeof(tagX); i++){ if(c[0] == stX[i].key){ stX[i].func(); break; } } return 0; }
呼び出した関数の中で引数にセットした関数を呼び出します。
#include <stdio.h> void func1(void (*func)(int)){ /* 引数に関数ポインタを指定 */ func(1); func(3); } void func_A(int a){ printf("%d",a); } void func_B(int a){ printf("%d", a*2); } int main(){ func1(func_A); func1(func_B); return 0; }
関数ポインタなしで書くと、func1から値を取得→func_A、func_Bに代入、という流れになります。(当然func1はvoid型のままでは無理です。)
#include <stdio.h> int func1(){ return 1; } int func2(){ return 3; } void func_A(int a){ printf("%d",a); } void func_B(int a){ printf("%d", a*2); } int main(){ int i; /* func_A(func1())などという書き方もできるが、 関数ポインタとの違いを明確にするため、この様な形にした。 */ i = func1(); func_A(i); i = func2(); func_A(i); i = func1(); func_B(i); i = func2(); func_B(i); return 0; }
関数ポインタは慣れないと使いどころが難しいですが、うまく使えばスマートなプログラミングが出きるようになりますので、いろいろやってみましょう。