目次

ニュース

日記カテゴリ

書庫

午前中に書いた 関数ポインタのみ!の続き。

関数ポインタってどんな風に使うのでしょう?

普通にポインタで貼っているだけなら、わざわざポインタを使う必要がないのですが、ポインタの配列を使うと威力が発揮できます。

デリゲートと同様に戻り値と引数が同じ関数を配列にすることで、「何番目の関数を呼び出す」という動きが使えます。記述方法としては、

戻り値 (*ポインタ名[])(引数リスト);

?

これもあまりよい使い方ではないのですが、使用例です。

#include

/* 足し算 */
double calcAdd(int a, int b) {
  return a + b;
}

/* 引き算 */
double calcSub(int a, int b) {
  return a - b;
}

/* 掛け算 */
double calcMux(int a, int b ) {
  return a * b;
}

/* 割り算 */
double calcDiv(int a, int b) {
  return (double)a / b;
}

int main() {
  /* 関数ポインタを配列化する */
  double (*calc[])(int, int) = { calcAdd, calcSub, calcMux, calcDiv };
  int a,b,i;

  /* 演算元を入力 */
  printf("実行元の変数Aを入力 > ");
  scanf("%d",&a);

  printf("実行元の変数Bを入力 > ");
  scanf("%d",&b);

  /* 逐次呼び出しで上記関数を実行 (わざとループにしてます) */
  for ( i = 0 ; i < 4 ; i++ ) {
  switch ( i ) {
  case 0:
    printf("Function[%d] 実行結果 = %f\n", i, calcAdd(a,b));
    break;
  case 1:
    printf("Function[%d] 実行結果 = %f\n", i, calcSub(a,b));
    break;
  case 2:
    printf("Function[%d] 実行結果 = %f\n", i, calcMux(a,b));
    break;
  case 3:
    printf("Function[%d] 実行結果 = %f\n\n", i, calcDiv(a,b));
 }
 }


/* ループで上記関数を順次実行 */
for ( i = 0 ; i < 4 ; i++ ) {
  printf("Function[%d] 実行結果 = %f\n", i ,calc[i](a,b) );
}
 return 0;
}

実行すると、引数Aと引数Bをコンソールで入力すると、それぞれの四則演算を行います。

実行元の変数Aを入力 > 3
実行元の変数Bを入力 > 2
Function[0] 実行結果 = 5.000000
Function[1] 実行結果 = 1.000000
Function[2] 実行結果 = 6.000000
Function[3] 実行結果 = 1.500000

Function[0] 実行結果 = 5.000000
Function[1] 実行結果 = 1.000000
Function[2] 実行結果 = 6.000000
Function[3] 実行結果 = 1.500000

関数名を明示的にソースコード上にかかなくても、「配列にしまっておいた何番の関数」といった呼び出しができます。

上記の場合はループで行っていますが、コマンドの番号によって処理を分岐するといったルーチンを作成するときに、switch文やif文で切り分けなくても呼び出したい関数を登録しておくことで、動的に関数を呼び出したりすることができるようになりますね。

投稿日時 : 2007年10月25日 17:42
Feedback
  • # re: 関数ポインタの配列
    凪瀬
    Posted @ 2007/10/25 17:54
    コールバック関数とかが良く使われる例なんじゃないですかね。
  • # re: 関数ポインタの配列
    ながせ
    Posted @ 2007/10/25 18:05
    C#のFormsのハンドラなんかでは、デリゲートの継承型になってますし、コールバック関数には適してますよね。基本的に型が同じだし。
  • # re: 関数ポインタの配列
    2リットル
    Posted @ 2007/10/25 18:19
    状態とそのときの処理でテーブルを作るイメージですね。

    関数ポインタはDLLの動的ロードでしか使ったことがないので、めからうころです。
  • # re: 関数ポインタの配列
    とっちゃん
    Posted @ 2007/10/25 18:51
    Windows な世界だと、コールバック関数でお世話になりますね。

    SDK のレベルであれば、WndProc は一度は必ず関数ポインタ化されますしw
    #わかってなくて使ってる人多いですけどw

    EnumなにがしなAPIも同様なものが多いなぁw

    C の世界だと、qsort が有名なわけですが...
    #そうと知らずに使ってる人は多い気がする...orz

  • # re: 関数ポインタの配列
    ながせ
    Posted @ 2007/10/25 20:51
    >2リットルさん
    ありがとございます。その通りです。
    処理テーブルもプログラム中で書き換えることができるので、ある意味動的プログラミング^-^;

    >とっちゃん
    WndProcの件でいろんなものに目覚めました。

    でも最近じゃSDKをいぢったりとかdllの内部をアセンブラレベルで追ったりする人ってすごく一部になってしまいましたねー。
  • # re: 関数ポインタの配列
    επιστημη
    Posted @ 2007/10/26 2:20
    二次元配列でこれやれば状態遷移表が実装できるよねー
  • # re: 関数ポインタの配列
    ながせ
    Posted @ 2007/10/26 9:44
    そっですねー。
    組み込み用途だと、プログラムを冗長に書くのが嫌がられる傾向があるので、よくやってます。
  • # TwlbPCUeUHjeYSo
    johnanz
    Posted @ 2022/04/19 14:17
    http://imrdsoacha.gov.co/silvitra-120mg-qrms
タイトル
名前
Url
コメント 

Blog 利用状況

コミュニティ

プロファイル