C言語は関数の引数に関数へのポインタを渡すことができます.これにより擬似的な高階関数 (higher order function) を作成することができます.
例えば, double 型を戻り値とし,int 型の引数を 2 つ持つ関数へのポインタを仮引数にとる関数は以下のように定義することができます.
void example(double (*func)(int, int));
以下に関数の引数に関数へのポインタを渡すサンプルプログラムを示します.
/* header files */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* functions */
int odd(int val);
int even(int val);
int filter(int (*func)(int), int *items, int *results, int n);
/* main */
int main(void) {
int items[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int odds[9] = {0};
int evens[9] = {0};
int i, n;
/* 配列の中身を表示 */
printf("実行前: ");
for ( i = 0; i < 9; i++ ) printf("%d ", items[i]);
printf("\n");
/* 偶数のデータのみを取得 */
n = filter(odd, items, odds, 9);
/* 結果を表示 */
printf("奇数だけを取得: ");
for ( i = 0; i < n; i++ ) printf("%d ", odds[i]);
printf("\n");
/* 奇数のデータのみを取得 */
n = filter(even, items, evens, 9);
/* 結果を表示 */
printf("偶数だけを取得: ");
for ( i = 0; i < n; i++ ) printf("%d ", evens[i]);
printf("\n");
return EXIT_SUCCESS;
}
/**
* 奇数かどうかを判定する
* @param[in] val 判定対象の値
* @retval 真 奇数
* @retval 偽 偶数
*/
int odd(int val) {
if ( val & 1 ) {
return 1;
} else {
return 0;
}
}
/**
* 偶数かどうかを判定する
* @param[in] val 判定対象の値
* @retval 真 偶数
* @retval 偽 奇数
*/
int even(int val) {
if ( !(val & 1) ) {
return 1;
} else {
return 0;
}
}
/**
* 配列にフィルタをかけ, results に格納して返す.
* @param[in] func int型の引数を1つもつ真偽値を返す関数へのポインタ
* @param[in] items フィルターをかける配列
* @param[out] results 結果を格納する配列
* @param[in] n itemsの要素数
* @return resultsの要素数
*/
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;
}
サンプルプログラムの実行結果は以下のようになります.
実行前: 1 2 3 4 5 6 7 8 9 奇数だけを取得: 1 3 5 7 9 偶数だけを取得: 2 4 6 8
たくさんあるC言語関連の書籍の中でも特に役に立った本です.よかったら参考にしてみてください.
C言語の実践的参考書.少々値段は張りますが初心者を脱しようとしている人は絶対に読むべきです.
文法だけでなく,コーディングスタイルやデバッグなど文字通り「実践的」なことが書かれているので非常にためになります.
オライリーの本は,読みにくい本が多いのですが本書はとても読みやすくオススメです.
ポインタの解説書としては最高の書籍です.
この1冊でポインタを完全に理解することができます.全くの初学者が読むには敷居が高いですが,入門書を読み終えた後に読むと非常に有益です.