- ベストアンサー
関数ポインタの利点
こんにちは。 C言語初心者ですが今勉強中です。 その中でポインタについては理解できたのですが、 関数ポインタの利点、使うべき所などが理解できません。 ポインタの基本は理解しています。 値渡し、アドレス渡しも理解しています。 関数ポインタを使うと何がいい、またはどんなとき使わなければならないのか 教本を読んでいてもさっぱりわかりません。 サンプルプログラムを打っても何のために使ってるのかわからないです。 どなたか教えていただけませんでしょうか? よろしくお願いします。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
実際に関数へのポインタを使用している事例を調べるのが一番手っ取り早いと思います。 標準関数だけでも、atexit、bsearch、qsort、signalが関数へのポインタを使用しています。一度、触ってみるとよいでしょう。 ところで、余談かもしれませんが、関数へのポインタがなければ関数を呼び出すことができません。 関数呼出し演算子(括弧演算子)がオペランドとして要求するのは、関数型ではなく、関数へのポインタ型だからです。すなわち、 voif func(void); func(); のようにfuncを呼び出す場合でも、funcは関数へのポインタ型(ここではvoid(*)(void)型)に暗黙的に型変換され、関数呼出し演算子のオペランドになっているわけです。
その他の回答 (5)
- jacta
- ベストアンサー率26% (845/3158)
これまでの回答で、ほぼ出揃ったと思いますが、要約すると、 ・(広い意味で)コールバックとして使用する。 ・関数テーブルとして使用する。 というのが一般的な使い方です。 コールバックは、特定の状況に対するハンドラを設定するために使用することが大多数です。 関数テーブルは、例えばswitch文の代わりに、処理を表引きさせたい場合などに有効です。特に、switch文では、データと処理の関係を動的に変更できませんが、関数テーブルであれば、どのようにでもできます。 テーブルを引き当てるのは、何も連番でなくてもよいわけで、文字列等を使って連想配列にすることも可能です。 標準関数のatexitやsignalは、上記の2つをあわせた特徴を持っています。ユーザーには見えませんが、これらの関数は、内部的に関数テーブルを管理しているのです。 C++では、関数へのポインタから一歩進んで、関数オブジェクト(あるいはファンクタ)というものを使いますが、これはどちらかというとコールバック的な概念です。
- linus1974
- ベストアンサー率19% (71/370)
そうですねえ。gtk+のイベントなんか参考に なりますかね。 極論をいうとライブラリやフレームワークを 作る人のためのものじゃないかと思います。 一般のソフト開発ではほとんどつかわないですね。 私が知っているのは、 組込み系でC++で開発したいけど、そのマイコン のコンパイラはCしかないとき、オブジェクト 指向のポリモーフィズムを 関数ポインタで解決することはあります。
- FAY
- ベストアンサー率49% (95/193)
あとはダイナミックリンクライブラリ内でエクスポートされた 関数のアドレスを取得するGetProcAddress()なども 関数のアドレスを戻り値として返すので これを関数ポインタで受け取ったりします。
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
#1でも挙げられていますが、 例えば、qsort の様な汎用のソート関数の場合、 例えば、構造体のような汎用なデータを比較する必要があるわけですが、そのどの部分で比較すればいいのかわかりませんから、その手順としての(比較)関数を渡して使うというようなコトがあります。 あと、例えばFORTHのような処理系を作成することを考えると、 FORTHはいってみれば関数呼び出しの固まりみたいなものなんですが、このようなインタプリタについては、呼び出す関数が実行時でないと決まらないので、関数名で関数の呼び出しができません。 そのような場合に関数のポインタを使って関数を呼び出します。
- peko_pee
- ベストアンサー率53% (45/84)
ちょっと高度な用法ですが、関数ポインタを Type (*func[ ])(.....) = { func0, func1, func2, .... }; のように配列にしておくと func[ ](.....); の [ ] 内の数値を変えるだけで呼び出す 関数を変えられるという使い方ができます。 逆に、複数の関数に同じ引数を与えるような処理をしたい場合も上のように配列に なっていると、 for (i = 0; i < XX ; i++) func[i](.....); と記述できます。 呼び出す関数が3つ4つなら if 文でも呼び分けられますが、多くなればなるほど こういう形にせざるを得ないと思います。 関数ポインタは標準関数の引数として必要になることはもちろんですが、実際に プログラムを作るときには単独よりも配列で使うことのほうが多いのではないかな という気がします。