おさえておきたいプログラミングの基本
ポインタとして保持できるのは、何も変数だけではありません。関数もまた、ポインタとして利用できます。これを、関数ポインタと言います。実際に、簡単なサンプルを見てみましょう。
listex3-fp-1:main.c#include <stdio.h>
// 関数のプロトタイプ宣言
void func1();
void func2();
int main(int argc,char** argv){
void (*fp)() = func1; // 関数ポインタをfunc1で初期化
fp(); // 関数fpを実行
fp = func2;
fp(); // 関数fpを実行
return 0;
}
// 関数1
void func1(){
printf("func1\n");
}
// 関数2
void func2() {
printf("func2\n");
}
実行結果
このプログラムの8行目で定義されている、fpが、関数のポインタです。関数のポインタの書式は、以下の通りになっています。
期待される実行結果の例 関数ポインタの書式という形になります。ここで用いている、func1()および、func2()は、戻り値の型がvoidであり、引数がないので、()無いが空白で、変数名がfpであることから、void (*fp)と宣言します。
型の定義の仕方こそ特殊ですが、関数ポインタも、ポインタ変数の一種です。ただ、そこに代入するのはあくまでも関数です。
関数ポインタが代入された変数は関数として扱うことが出来、関数名(引数)の組み合わせで呼び出すことができます。
関数ポインタで関数を実行するこの時実行されるのは、fpに代入された関数です。
続いて、関数に引数がある場合のケースを見てみましょう。以下のサンプルを実行してみてください。
listex3-fp-2:main.c#include <stdio.h>
// 引数のある関数ポインタ
int max(int,int);
int min(int,int);
int main(int argc,char** args){
int (*cmp)(int,int) = max; // cmpの初期化と(max)
int a = 1,b = 2;
printf("%dと%dのうち、最大のものは、%d\n",a,b,cmp(a,b));
cmp = min; // cmpにminを代入
printf("%dと%dのうち、最小のものは、%d\n",a,b,cmp(a,b));
return 0;
}
// 最大値を返す関数
int max(int m,int n)
{
if(m > n){
return m;
}
return n;
}
// 最小値を返す関数
int min(int m,int n)
{
if(m < n){
return m;
}
return n;
}
実行結果
ここで宣言されている2つの関数min、maxはともに引数として2つの整数、戻り値の型がintです。そのため、以下のように宣言された変数に代入することが可能です。(8行目)
関数ポインタ変数の宣言変数cmpには、初期値としてmac関数のポインタが代入されていますが、同じ引数の組み合わせ、同じ戻り値の型の関数minのポインタを代入できます。(11行目)
続いて、さらに高度な使い方を見てみましょう。関数ポインタは、さらに、他のポインタ同様、関数の引数として渡すことも可能です。ためしに、以下のサンプルを実行してみてください。
listex3-fp-3:main.c#include <stdio.h>
// 関数ポインタを引数としてとる関数
void funcp(int (*)(int),int n);
// 関数ポインタに用いる関数
int dbl(int);
int hlf(int);
int main(int argc,char** args){
funcp(dbl,8); // 引数として、関数を渡す
funcp(hlf,8); // 引数として、関数を渡す
return 0;
}
void funcp(int (*f)(int),int n){
printf("引数:%d 結果%d¥n",n,f(n));
}
// 最大値を返す関数
int dbl(int n){
return n * 2;
}
int hlf(int n){
return n / 2;
}
実行結果
4行目で、関数ポインタを引数として持つ関数、funcp()のプロトタイプ宣言をしています。プロトタイプ宣言の中で、関数ポインタを宣言するときは、以下のようになります。
引数内での関数ポインタの書式普通の引数と同様、関数ポインタの宣言から、変数名を抜いた形にすればよいことがわかります。関数名は、対応する関数の定義の中で記述します。15行目)
このサンプルでは、この引数として、関数dblおよび、hlfを与えています。引数として与えられた関数は17行目で実行されていますが。関数が違えば、当然のことながら実行結果は違ってきます。
このように、関数ポインタは、呼び出す関数を動的に変更する時に非常に便利です。
練習問題 : 問題3.
一週間でわかるC言語・C++言語がオンライン講座になりました!動画と音声によってさらにわかりやすくなりました!! 1講座で2つの言語を学ぶことができる上に、練習問題の回答もダウンロードできます。
Read →本講座が「1週間でC言語の基礎が学べる本」として書籍化されました!サイトの内容プラスアルファでより学習しやすくなっています!Impressより発売中です!!
Read →