関数の引数として関数ポインタを渡す

関数の引数に、関数ポインタを渡すことによって、高階関数のようなことができる。

次のプログラムは、整数の配列にフィルタをかけてその結果を表示する。Filter() 関数は奇数だけを残すために Odd()、偶数だけを残すために Even() をそれぞれ受け取ることで、ひとつの関数で 2 種類のフィルタとして動作している。

#include

#define MAX 10

int Odd(int val);
int Even(int val);
int Filter(int (*func)(int), int items[], int results[], int n);

int main(void)
{
    int items[MAX] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int odds[MAX];
    int evens[MAX];
    int i, n;

    printf("before: ");
    for (i = 0; i < MAX; i++) {
        printf("%d ", items[i]);
    }
    printf("\n");
    n = Filter(Odd, items, odds, MAX);
    printf("odds: ");
    for (i = 0; i < n; i++) {
        printf("%d ", odds[i]);
    }
    printf("\n");
    n = Filter(Even, items, evens, MAX);
    printf("evens: ");
    for (i = 0; i < n; i++) {
        printf("%d ", evens[i]);
    }
    printf("\n");

    return 0;
}

int Odd(int val)
{
    if (val & 1) {
        return 1;
    } else {
        return 0;
    }
}

int Even(int val)
{
    if (!(val & 1)) {
        return 1;
    } else {
        return 0;
    }
}

int Filter(int (*func)(int), int items[], int results[], int n)
{
    int i, j = 0;

    for (i = 0; i < n; i++) {
        if ((*func)(items[i])) {
            results[j++] = items[i];
        }
    }

    return j;
} 
takatoh@nightschool $ gcc -Wall filter.c -o filter
takatoh@nightschool $ ./filter
before: 1 2 3 4 5 6 7 8 9 10 
odds:   1 3 5 7 9 
evens:  2 4 6 8 10

ところで、関数ポインタの型は引数名は書かなくてもいいんだな。つまり、

int (*func)(int val)

じゃなくて

int (*func)(int)

でいいということ。