関数ポインタとは 「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;
}
関数ポインタは慣れないと使いどころが難しいですが、うまく使えばスマートなプログラミングが出きるようになりますので、いろいろやってみましょう。