• 締切済み

関数ポインタの型をtypedefしたとき

C言語において、関数ポインタの型をtypedefで作ると、 typedef int (*MyFunc)(int*,int*); と宣言でき、関数ポインタの変数は、 int FuncA(int* a, int* b) { ~ } void main_loop() { MyFunc pf = FuncA; ~ (*pf)(pa,pb); } というように使うと思います。 ここで疑問なのですが、この実際に呼び出される関数、FuncAの定義に、typedef(ここではMyFunc)を使えないものでしょうか? 同じことを2回やっているようで、無駄に思えてしまいます。

みんなの回答

  • ency
  • ベストアンサー率39% (93/238)
回答No.5

C では、式の中の関数名だけが関数を指すポインタに読み替えられます。 # これは、コンパイラが勝手に読み替えます。 関数定義やプロトタイプ宣言といった、式の中にない関数名はポインタに読み替えられることはありません。 ですので、ご質問の中にある > typedef int (*MyFunc)(int*,int*); と > int FuncA(int* a, int* b) > { > ~ > } は、別の型ということになります。 FuncA( pa, pb ); // FuncA はポインタに読み替えられている。 と関数を式の中に記述した場合にのみ、コンパイラがこの FuncA をポインタとして読み替えるんです。 式の中という意味では、以下の場合も同様です。 MyFunc pf = FuncA; // FuncA はポインタに読み替えられている。 実際、pf に FuncA を代入する場合、以下のようにしても正常に動作します。 MyFunc pf = &FuncA; // アドレス演算子 & をつけてみる。 ついでに、(*pf)() コールの箇所も、以下のようにすることができます。 pf(pa,pb); // 間接参照演算子 * をとってみた。 つまり、関数を指すポインタに「限って」いえば、間接参照演算子はあってもなくても良い存在です。 というわけで、こんなことをしてもコンパイルエラーにも実行エラーにもなりません。 (**********pf)(pa,pb); // どうせ * は何もしないし。。。 このように、関数のポインタ周りの仕様はかなり混乱しています。 配列とポインタが違うものであるように、関数と関数ポインタも別物です。 どちらも、C のコンパイラが自分の都合でポインタに読み替えているだけです。 こんな感じでいかがでしょうか。

回答No.4

関数ポインタに代入する関数が、1つで決まってるなら無駄といえば無駄ですね。 この場合なら int FuncA(int* a, int* b){~} void main_loop(){  FuncA(pa,pb); } で十分です。 関数ポインタが必要になるような例は。 typedef int (*MyFunc)(int*,int*); int FuncA(int* a, int* b){ ~ } int FuncB(int* a, int* b){ ~ } void main_loop(){  MyFunc pf;  if (flag) {   pf = FuncA; // flagが真であればFuncAを呼び出す  } else {   pf = FuncB; // flagが偽であればFuncBを呼び  }  (*pf)(pa,pb); } こうゆう使い方なら納得できるとかと思います。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

多分, できないと思います. 該当する例は見付ていないのですが, The identifier declared in a function definition (which is the name of the function) shall have a function type, as specified by the declarator portion of the function definition. とあって, ここに対する脚注として The intent is that the type category in a function definition cannot be inherited from a typedef. と書かれており, その例として以下が規格に挙げられています: typedef int F(void); F f, g; // f and g both have type compatible with F F f { /* ... */ } // WRONG: syntax/constraint error F g() { /* ... */ } // WRONG: declares that g returns a function 脚注部分で「the type category in a function definition cannot be inherited from a typedef」と書かれているので, typedef int (*PF)(void); でも PF *f { /* ... */ } はアウトだと思います.

racoon_asia
質問者

お礼

こういうものだと思うことにします^^; ご丁寧にありがとうございました。

noname#198419
noname#198419
回答No.2

おそらく参考書を読みながら質問しているのかと思いますが、参考書では関数のポインタを手短に説明するために質問にあるようなコードが提示されているんだろうと思います。 もう少し発展させて・・・ MyFunc pf; ではなく、単純なリスト構造にするために MyFunc pf[100]; とかだったら、(配列の終わり判定を含めて)100個までの処理を並べることができますよね。 あとは添え字をインクリメントしていけば、バッチ言語処理のようなことが出来そうな気がしてくれば、C言語のプログラミングを勉強した甲斐があったというものでしょう。 もっと詳しく知りたいのならば、 「実用Cプログラミング生 粋のCプログラマへ」H.シュルト著 http://www.fukkan.com/vote.php3?no=19161 とか 「エキスパートCプログラミング - 知られざるCの深層 -」Peter van der Linden著 などといった、K&Rを卒業した中級以上のスキルを対象にする本を眺めてみることです。

  • skbler
  • ベストアンサー率9% (69/691)
回答No.1

MyFunc pf = FuncA; 代入(メモリ上に値を記憶するための必要な領域を確保) (*pf)(pa,pb); 演算処理?