C言語の基礎 - 関数ポインタ

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

ポインタの参照先を関数にすると、そのポインタが指し示す関数を呼び出すことができる。
ポインタに格納する関数のアドレスを変えることで、呼び出す関数を動的に変更することが可能となる。


関数ポインタの使用方法

関数ポインタは、アドレスを格納する関数と同じ戻り値の型を使って宣言する。
関数ポインタの仮引数の型と、ポインタに格納する関数の型は一致させる必要がある。

関数ポインタを使う時は、下記のようにポインタ名に()を付けて使用する。
型 (*変数名)(仮引数)

 #include <stdio.h>
 
 int addition(int x, int y);
 int subtraction(int x, int y);
 
 int main(int argc, char *argv[])
 {
    int answer = 0;
    int (*pFunc)(int, int);
 
    pFunc = addition;
    answer = (*pFunc)(5, 3);
    printf("a + b = %d\n", answer);
 
    pFunc = subtraction;
    answer = (*funcp)(10, 7);
    printf("a - b = %d\n", answer);
 
    return 0;
 }
 
 int addition(int x, int y)
 {
    return x + y;
 }
 
 int subtraction(int x, int y)
 {
    return (x - y);
 }

1度目の関数呼び出し時は、pFuncに関数additionのアドレスが格納されており、
2度目の関数呼び出し時は、関数subtractionのアドレスが格納される。
このようにして、ポインタに関数のアドレスを格納することで、呼び出す関数を変更することができる。

関数ポインタの仮引数は、仮引数の型だけを入れて宣言すればよい。

ちなみに、以下のように宣言して配列として使うこともできる。

 int main(int argc, char *argv[])
 {
    int answer;
    int (*pFunc[])(int, int) = { addition, subtraction };
 
    answer = (*pFunc[0])(5, 3);
    printf("a + b = %d\n", answer);
 
    answer = (*pFunc[1])(10, 8);
    printf("a - b = %d\n", answer);
 
    return 0;
 }



コールバック関数を使用する

下記のように、コールバック関数として使用することができる。

 #include<stdio.h>
 
 typedef void (* PFUNC)(char *);
 
 void printText1(char *s);  // 文字列をそのまま出力
 void printText2(char *s);  // 文字列を""で囲んで出力
 void exec(char *s, PFUNC p);
 
 int main(int argc, char *argv[])
 {
    PFUNC pFunc;
 
    pFunc = printText1;
    exec("ぷりんとてきすと1", pFunc);
 
    pFunc = printText2;
    exec("ぷりんとてきすと2", pFunc);
 
    return 0;
 }
 
 void printText1(char *s)
 {
    printf("%s\n", s);
 }
 
 void printText2(char *s)
 {
    printf("\"");
    printf("%s", s);
    printf("\"\n");
 }
 
 void exec(char *s, PFUNC pFunc)
 {
    pFunc(s);
 }



typedefを使用する(C++11以降)

C++11以降の場合、typedefを使用することを推奨する。

 // C++98, C++03の記述
 typedef void (*pfunc)(int, char);
 
 // C++11以降の記述
 using pfunc = void (*)(int, char);