関数ポインタ

関数ポインタは、関数のエントリポイントのアドレスを保持する変数。
コンパイラは、プログラムをコンパイルするときに関数のエントリポイントを作成する。エントリポイントはアドレスなので、それを指すポインタ変数を持つことが可能だ。それが関数ポインタ。

関数ポインタを宣言するには、その関数の戻り値の型のポインタとして、関数に引数があればそれも続けて宣言する。

int (*p) (int x, int y);

優先順位の規則のため、*p はカッコで囲む必要がある。

関数のアドレスを関数ポインタに代入するには、関数名をカッコを付けずに指定する。例えば、次のような関数 sum() があるとすると:

int sum(int a, int b);

次のように代入する。

p = sum;

代入した関数を呼び出すには:

result = (*p) (10, 20);

呼び出し時にも *p をカッコで囲む必要がある。

戻り値の型と引数の数、型が同じであれば、関数ポインタを配列にすることもできる。

int (*p)[4] (int x, int y);

次のプログラムは、ユーザに2つの整数を入力させ、次に行いたい演算の番号を入力させる。そしてその結果を表示する。
ユーザの入力した番号から演算を選ぶ部分で関数ポインタの配列を使っている。

#include

int sum(int a, int b);
int subtract(int a, int b);
int mul(int a, int b);
int dev(int a, int b);

int (*p[4]) (int x, int y);

int main(void)
{
    int result;
    int i, j, op;

    p[0] = sum; /* Get address of sum() */
    p[1] = subtract; /* Get address of subtract() */
    p[2] = mul; /* Get address of mul() */
    p[3] = dev; /* Get address of dev() */

    printf("Input 2 numbers:\n");
    scanf("%d%d", &i, &j);
    printf("0: sum, 1: subtract, 2: mul, 3: dev\n");
    do {
        printf("Input number of operation:\n");
        scanf("%d", &op);
    } while ((op < 0) || (3 < op));
    result = (*p[op]) (i, j);
    printf("%d\n", result);
    return 0;
}

int sum(int a, int b)
{
    return a + b;
}

int subtract(int a, int b)
{
    return a - b;
}

int mul(int a, int b)
{
    return a * b;
}

int dev(int a, int b)
{
    if (b) {
         return a / b;
    } else {
        return 0;
    }
}
takatoh@nightschool $ ./sample_12_6
Input 2 numbers:
57
24
0: sum, 1: subtract, 2: mul, 3: dev
Input number of operation:
2
1368