トップC言語入門 > コールバック

コールバック

1.コールバックとは

コールバックとは下の例に示すように、関数を引数にとるものである。

callback01.c
#include<stdio.h>
#include<math.h>

double sum(double x, double y) {
    return x + y;
}

double calc(double x, duble y, double (*func)(double,double)) {
    return func(x, y);
}

int main(){
    double res = calc(2.0, 3.0, sum); // sumをコールバック
    printf( "res = %f\n", res);
    res = calc(1.41, 2.0, pow); 	 // ライブラリ関数powをコールバック
    printf( "res(1.41の2.0乗) = %f\n", res);
}
[参考文献: http://www.officeuchida.com/pdt/pdtsamp3.html]

実行結果を下に示す。calc(2.0, 3.0, sum)の場合、 sum関数をコールバックするため、加算結果が得られる。 calc(1.41, 2.0, pow)とすると、階乗計算を行うpow関数をコールバックするため、 階乗計算が行われる。

c:\MH\www\c01\callback>callback01
res = 5.000000
res(1.41の2.0乗) = 1.988100

仮引数の書き方は

double calc(double x, duble y, double func(double,double)) {
    return func(x, y);
}
または
double calc(double x, duble y, double func()) {
    return func(x, y);
}
でもよい。 funcの後ろの ( ) は、この引数が関数ポインタ(function pointer)であることを表したものであり、 省略できない。

2.コールバック関数を使ったデータの並び替え

コールバック関数を引数するものとして、C言語では 標準ライブラリ関数qsortがよく知られている。 下に例を示す。比較関数を用意するだけで、配列データの並び替えが簡単に行える。 構造体配列の場合、比較関数を取り替えるだけで、並び替え規則は自由自在である。 キャストとアロー演算子が登場するので、初心者には難しいが、是非、マスターすべき技術である。

callback02.c
#include <stdio.h>
#include <stdlib.h>

typedef struct _DATA { int  n; char *s; } DATA;

DATA data[] = { {30, "abc"}, {20, "123"}, {60, "xyz"}, {10, "ijk"} };
#define ARRAY_SIZE  (sizeof(data) / sizeof(DATA))

void print_array(DATA *data, int num) {
    int n;
    for (n = 0; n < num; n++) {
	printf("%d %s\n", data[n].n, data[n].s);
    }
}

// 数値の小さい順に並べ替えるための比較関数
int compInt(const void *a, const void *b) {
    return ((DATA*)a)->n - ((DATA*)b)->n;
}

// 文字コード順に並べ替えるための比較関数
int compStr(const void *a, const void *b) {
    return strcmp(((DATA*)a)->s, ((DATA*)b)->s);
}

int main() {
    printf("元のデータ\n");
    print_array(data, ARRAY_SIZE);      /* ソート前の配列を出力 */
    printf("\n");
    qsort(data, ARRAY_SIZE, sizeof(DATA), compInt);  /* クイックソート実行   */
    printf("数値の小さい順に並び替えた結果\n");
    print_array(data, ARRAY_SIZE);      /* ソート後の配列を出力 */
    printf("\n");
    qsort(data, ARRAY_SIZE, sizeof(DATA), compStr);  /* クイックソート実行   */
    printf("文字コード順に並び替えた結果\n");
    print_array(data, ARRAY_SIZE);      /* ソート後の配列を出力 */
}
c:\MH\www\c01\callback>callback02
元のデータ
30 abc
20 123
60 xyz
10 ijk

数値の小さい順に並び替えた結果
10 ijk
20 123
30 abc
60 xyz

文字コード順に並び替えた結果
20 123
30 abc
10 ijk
60 xyz