状態遷移図をコードに落としたり、オブジェクト指向の多態性(polymorphism)をCのコードで実現したりする場合、呼び出す関数を動的に変更する必要があります。
このページでは、「呼び出す関数を動的に変更する」ような実装を可能にする関数ポインタについて説明します。
関数ポインタとは、C言語における重要な概念である「ポインタ」の関数版です。
ポインタはあるメモリアドレスを指す「矢印」ですが、関数ポインタは「関数が格納されたメモリアドレスを指す矢印」ということになります。
関数を呼び出す際に、関数ポインタの内容を別の関数が格納されたアドレスに変更することにより、呼び出す関数を任意に変更することが可能です。
関数ポインタのプロトタイプ宣言は下記の通りです。
引数の型や数は、関数ポインタを利用する状況に合わせて変更してください。
typedef int (*FUNCPTR)(int a,int b);
関数ポインタに格納する関数は、下記のように定義します。
基本的に通常の関数の定義と変わりありませんが、引数はプロトタイプ宣言された関数ポインタと型・数を揃えるようにしてください。
int multiple(int a,int b) { return(a*b); } int divide(int a,int b) { return(a/b); }
関数ポインタへの関数アドレスの格納は、下記のようにアドレス演算子「&」を用いて行います。
FUNCPTR tFuncPtr; tFuncPtr=&multiple;
関数ポインタに格納された関数アドレスを用いて関数を呼び出すには、下記のようにします。
int result; result=(tFuncPtr)(a,b);
以下に関数ポインタを用いた簡単なサンプルコードを示しますので、参考にしてください。
#include <stdio.h> typedef int (*FUNCPTR)(int a,int b); int multiple(int a,int b) { return(a*b); } int divide(int a,int b) { return(a/b); } void main() { int a,b; int result; FUNCPTR tFuncPtr; a=8; b=4; tFuncPtr=&multiple; result=(tFuncPtr)(a,b); printf("Answer is %d\n",result); tFuncPtr=÷ result=(tFuncPtr)(a,b); printf("Answer is %d\n",result); }
・頂いたメッセージは管理者のチェックの後、公開されます。
・メッセージの公開を希望されない場合には、「このメッセージを非公開にする」にチェックを入れてください。
・管理者が不適切と判断したメッセージは公開しませんので、予めご了承ください。
まさにこれだ 47 (49%) |
参考になった 20 (21%) |
ちょっと違う 10 (10%) |
これじゃない 19 (20%) |
【まさにこれだ】 動的に呼び出すというのが意義というのが始めに書いてあったので、納得感を持って読むことができた (2020/11/18 Wed 23:18:43)
【参考になった】 以下、御存じであれば、教授ください。
関数名「multiple」はそのままで関数へのポインタではないでしょうか?
「&」を付ける方が正しいでしょうか?
※「&」を付けなくても期待通りの動作をしており、どちらが正しいか知りたく。 (2020/05/15 Fri 22:12:33)
【まさにこれだ】 どこよりも分かり易いです。 (2018/02/22 Thu 22:03:40)
【まさにこれだ】 分かりやすかったです。 (2017/05/11 Thu 16:32:46)
【ちょっと違う】 > void main()
ANSI 非準拠
C89 非準拠
(2016/09/01 Thu 10:18:40)