関数ポインタは「どこでもドア」
めっちゃ久しぶりに書いて行きます。テーマは関数ポインタです。ポインタについては、以前の記事で触れていますが関数ポインタについては今回は初になります。C言語において関数もメモリ上に配置されるので、当然アドレスがあります。アドレスがあると言うことはポインタ変数に格納できます。つまり、それが関数ポインタです。これは便利やでぇ。
エレベーターって「どこでもドア」じゃない?
幼少の頃どこかのデパートで人生初のエレベーターに乗りました。洋服売り場からエレベーターに入り扉が閉まります。次に開いた時・・・「なに!!オモチャ売り場やと!?」「どこでもドアってホンマにあったんかい!」と思いました。皆さんはそんな風に思ったことありませんか?その後母親にカラクリを聞いて、実際の仕組が理解できましたが、もしも「あ、あれ?どこでもドアやんか」と説明を受けていたら、信じていたことでしょう。今でもエレベーターに乗る時には、「どこでもドア~7階」と心の中で呟いて7階に移動する時があります。エレベーターってどこでもドアみたいっすよね。
関数ポインタについて
いきなり話が脱線しましたが、関数ポインタに話を戻しましょう。関数ポインタには関数のアドレスを入れることが出来ます。そして、関数ポインタ経由で関数にジャンプすることが出来るのです。一つの関数ポインタから色んな関数にジャンプ出来る点がどこでもドアみたいなんすよね。
関数ポインタの宣言方法
関数ポインタもポインタなので変数の一つです。なので宣言してから使用することになります。宣言方法は以下の通りです。
void (*func1)(void); // 戻り値:なし 引数:なし の関数ポインタの宣言
int (*func2)(int); // 戻り値:int 引数:int の関数ポインタ宣言
関数ポインタを宣言する場合、関数の戻り値の型、関数ポインタ名、関数の引数の型が必要になります。上の例の場合、(*func1)や(*func2)が関数ポインタ名になります。
関数ポインタの使い方
以下のコードがあったとします。これを実行するとどうなるか分かりますね。「test1 called」が出力されます。main関数からtest1関数を呼んでいるだけですね。
void test1(void)
{
printf("test1 called");
}
void main(void)
{
test1();
}
これと同じことを関数ポインタを使って記述すると次のようになります。
void test1(void)
{
printf("test1 called");
}
void main(void)
{
void (*Dokodemo)(void); // 関数ポインタを宣言
Dokodemo = test1; // 関数ポインタにtest1関数のアドレスを入れる
Dokodemo(); // 関数ポインタからtest1関数を呼び出す
}
Dokodemoという名前の関数ポインタにtest1関数のアドレスを入れた後、Dokodemo関数ポインタからtest1関数を呼び出しています。そのため実行結果は最初と同じく「test1 called」が出力されます。main関数内の3行をドラえもん風に説明すると以下のようになります。
1)どこでもドア~(関数ポインタ宣言)
ドラえもんが四次元ポケットからどこでもドアを引っ張り出したシーン
が1行目になります。
2)行先を告げる (関数ポインタにジャンプ先の関数アドレスを入れる)
どこでもドアの前で行先を告げるシーンが2行目になります。
3)ドアに入る (目的の関数にジャンプする)
どこでもドアに入って目的地に移動するシーンが3行目になります。
使い方は分かったけども
さて、これで関数ポインタの使い方が分かったけれども、なんでこんなことすんねん?関数ポインタ使わん方がコード量少ないやん。その通りです。1行で済むところが3行になってますね。単純な例で説明したためにこんな結果になっていますが、当然実践ではこんなことはしません。上の例の場合、test1関数を直接呼べば済む話です。しかし、どこでもドアの意味を考えて下さい。あれの便利な所は一つのドアで色んな所に行ける点です。同じ入り口で違う出口に出られる点です。プログラムにおける入り口のことをインターフェースと言います。同一インターフェースで異なる関数にジャンプできるのは非常に便利なことなのです。例題ではDokodemo = test1;としており、関数ポインタと関数が1対1の関係ですが、test2、test3・・・test100と仮にこんな状態になったとしても、全ての関数に対してDokodemo関数ポインタからジャンプすることができるのです(下のイメージ図を参照)。より実践的な話は次回以降にします。
まとめ
今回は関数ポインタについて書きましたが、関数ポインタはC言語において中級/上級者向けの話になります。これが一切使えなくてもプログラミングは出来ますが、使えた方が楽にコードが書けるようになります。何せどこでもドアっすからね。楽になるに決まっている。使えないより使えるに越したことはないでしょう。プロは皆使っています。次回実践編に入ります。それじゃまた。