関数へのポインタ
変数と同じように関数にもアドレスが割り当てられます。
関数ポインタは、その関数のアドレスを扱うものです。
関数ポインタを使うことで、プログラム中の処理の切り替えをコンパクトに行うことができます。
関数ポインタの前にポインタをという方は、ポインタについてまとめていますので、よかったらご覧ください。
関数ポインタの使い方
関数ポインタの宣言は
関数戻り値の型 (* 関数名)(引数);
となります。
次の例は、関数ポインタを使って関数を呼び出すプログラムです。
#include <stdio.h>
void func(void);
main()
{
void (*ptr_f)();
ptr_f = func;
(*ptr_f)();
printf("end\n");
}
void func(void)
{
printf("Function of Pointer Test\n");
}
C:\prog>pointer_test3
Function of Pointer Test
end
戻り値voidで引数がない関数ポインタ、ptr_f に関数funcのアドレスを代入しています。
(*ptr_f)()によって、func関数が呼び出され、func関数の処理が実行されます。
この例では、関数ポインタを使う必要はないですが、次に示す状態遷移処理に関数ポインタを使う例では、その有用性がわかるのではないかと思います。
状態遷移設計
ここでは、2つの状態の例を示します。
状態遷移設計のプログラム例です。
上の状態遷移図には、イベント値として、0と1の2つが記載されていますが、このプログラムでは、イベントを受け取っていないため、event変数は、ゼロのままです。
イベントを受け取る関数を用意して、イベントを受け取るようにすれば、その値により、状態や処理を変えていくというプログラムができます。
また、状態遷移表の状態数が増えた場合、プログラムの関数ポインタの配列部を増やしていくことで対応できます。
#include <stdio.h>
int func1(int e);
int func2(int e);
int (*ptr_f[2])(int e) = {
func1,
func2
};
main()
{
int event = 0;
int state = 0;
int i;
for(i=0;i<3;i++){
state = (*ptr_f[state])(event);
}
printf("end\n");
}
int func1(void)
{
printf("Function1\n");
return(1);
}
int func2(void)
{
printf("Function2\n");
return(0);
}
C:\prog>state_transfer
Function1
Function2
Function1
end
状態遷移設計は、状態遷移図や状態遷移表を使ってシステムを設計する手法です。状態遷移表を使ってシステムを設計することで、プログラムを実装する前段階での設計チェックが容易になり、処理の漏れや抜けなど、早期に設計ミスを発見することができます。
また、状態遷移設計は、関数ポインタを使って実装でき、状態遷移の枠組みとその中で行われる具体的な処理を分離できるので、具体的な処理を組み替えることで、様々な問題に適用することができます。
応用例として押しボタンスイッチの状態を状態遷移設計で行った記事を書いていますのでご参考にしてみてください。
コメント