| 関数の動作にバリエーションを持たせたい場合は、その動作を指定するパラメータをつけることで実現できます。例えば次のようにします(プログラム中の ASSERT については別のページの解説を参照してください)。 | ||
|
||
| さて、これだとあらかじめ決められた種類の動作しか行なえません。あとで動作の種類を増やそうと思ったら、関数自体を書き換える必要があります。ということは、動作の種類を増やすたびに以前の動作が変わってしまわないように気をつけなければならないし、我々が人間である以上、間違えて以前の動作を壊してしまうかもしれません。 | ||
| そこで、関数ポインタを使います。関数ポインタを使えばひとつのポインタ変数で関数のエントリポイントを受け渡すことができるので、関数自体(すなわち何らかの動作)を引数にするようなことができます。次のプログラムは、関数ポインタによって動作を引数にしている例です。 | ||
|
||
| このとき CallerFunc の引数 pHello と呼び出される関数 Hello() はメモリの中で次のようになっています。前回のトピックで出てきた図とそっくりですね。 | ||
![]() |
||
このプログラムでは、 CallerFunc に渡すパラメータを別の関数(ただし同じ型の関数でなければなりません)に差し替えるだけでいろいろな動作をさせることができます。このような引数として渡す関数をコールバックルーチン(call back routine)または単にコールバックと呼びます。コールバックルーチンには次のような利点があります。
|
||
| 「動作を引数にできる 」ということをより理解するために、もうひとつ例題をやってみましょう。ANSI-C に atexit() という関数がありあます。次のようなプロトタイプです。 | ||
|
||
| これは、プログラムが終了するとき(つまり英語で " at exit")に、あらかじめ登録しておいたコールバック関数を実行するためのものです(詳しくはリファレンスマニュアルを参照してください)。これを使って無理矢理 "Hello, world" を書いてみましょう。 | ||
|
||
| メモリの中で何が起こっているか想像するのを忘れないでください! atexit() は引数として受け取った関数のアドレスを登録しておくための関数ポインタを内部に持っていて、main 関数が終了するときにそこに登録された関数を呼び出すのです。 | ||
atexit() 以外にもコールバックを使った ANSI-C の標準関数があります。次の関数について調べてみてください。
|
||
| 関数ポインタとコールバックを理解してしまえばメモリの完全制覇は目前です。次回はメモリに情報を格納するということはそもそもどういう意味なのかについて考えます。 | ||
("Hello, ANOTHER world!" は2001年11月から2002年11月にかけて作成されたコンテンツです。)