- ベストアンサー
#define文等について質問です
表題の件ですが、 プログラム読んでいて分からないことありましたので、 C言語の文法的なことですが、教えて下さいませ。 全然自信ないですが、自分の解釈も付けてみました… 質問(1) #define MP_RELEASEWIN(p) MP_FreeWin((IWindow **)&(p)) 中略 static void MP_FreeWin(IWindow ** ppif); 中略 static void MP_FreeWin(IWindow ** ppif) { 中略 } このような場合、最初の#defineは、 MP_RELEASEWIN(p)は、MP_FreeWin((IWindow **)&(p))だよ と定義しているけど、前方宣言にはなっていないから static voidでプロトタイプ宣言して、 最後に関数の定義を書いているって解釈で 合っているのでしょうか? 質問(2) #define MP_IWINDOW_SETVTBL(pVtbl, pfnEn, pfnRd, pfnHE, pfnDel) \ (pVtbl)->Enable = (pfnEn); \ (pVtbl)->Redraw = (pfnRd); \ (pVtbl)->HandleEvent = (pfnHE); \ (pVtbl)->Delete = (pfnDel) これって、 MP_IWINDOW_SETVTBL(pVtbl, pfnEn, pfnRd, pfnHE, pfnDel) を (pVtbl)->Enable = (pfnEn); \ (pVtbl)->Redraw = (pfnRd); \ (pVtbl)->HandleEvent = (pfnHE); \ (pVtbl)->Delete = (pfnDel) の4行部分で置き換えているのでしょうか? あと、(pfnDel)の最後だけ、「;」がないのは 約束事って理解でいいのでしょうか? 質問(3) #define CMediaPlayer_CancelRedraw(p) { CALLBACK_Cancel(&(p)->m_cbRedraw); (p)->m_bRedraw = FALSE; } こんなのがあるのですが、 これは質問(2)と同じ意味なのでしょうか? こっちにはカッコが付いているのですが、 これは、何か意味があるのでしょうか? 質問(4) QINTERFACE(IWindow) { // Releases the window resources void (*Delete)(IWindow * po); }; この void (*Delete)(IWindow * po); の部分は、どういう風に理解すればいいのでしょうか? カッコとか、*がついてますが… Delete(IWindow * po); とかいう関数に何かしているという意味なのでしょうか@@; 教えて下さい。 なんか、たくさん質問してますが、 よろしくお願い致しますm(__)m
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
質問(1) #define指令(文ではない)は前処理で解決されますから、プロトタイプ云々の話は関係ありません。 質問(2) あまりよい実装ではありませんが... > の4行部分で置き換えているのでしょうか? そうです。 > あと、(pfnDel)の最後だけ、「;」がないのは MP_IWINDOW_SETVTBL(pVtbl, pfnEn, pfnRd, pfnHE, pfnDel)の後に ; を付ける使い方を想定しているのでしょう。 私ならこんな実装ではなく、 #define MP_IWINDOW_SETVTBL(pVtbl, pfnEn, pfnRd, pfnHE, pfnDel) \ ((void)( \ ((pVtbl)->Enable = (pfnEn)), \ ((pVtbl)->Redraw = (pfnRd)), \ ((pVtbl)->HandleEvent = (pfnHE)), \ ((pVtbl)->Delete = (pfnDel)) \ )) のようにします。 質問(3) > これは質問(2)と同じ意味なのでしょうか? まあそうですね。 > こっちにはカッコが付いているのですが、 > これは、何か意味があるのでしょうか? 一貫性がないのはスキルが低いことの現われです。 こちらの方が先ほどより若干ましですが、式ではないのでやはり問題があります。 質問(4) > void (*Delete)(IWindow * po); > の部分は、どういう風に理解すればいいのでしょうか? 関数へのポインタです。
その他の回答 (5)
- aris-wiz
- ベストアンサー率38% (96/252)
>(1) >static voidでプロトタイプ宣言して、 >最後に関数の定義を書いているって解釈で 違います。 #define MP_RELEASEWIN(p) MP_FreeWin((IWindow **)&(p)は プリプロセッサの為、翻訳単位が異なります。 ソースコード内での MP_RELEASEWIN(ほげほげ) という記述に対して、 MP_FreeWin((IWindow **)&(ほげほげ); に置き換える為の識別子です。 >(2) >4行部分で置き換えているのでしょうか? Yes。 行の終端に「\」がついているので、それがついていない (pVtbl)->Delete = (pfnDel)の行までが1行とみなされ #defineでの置換対象になります。 >あと、(pfnDel)の最後だけ、「;」がないのは >約束事って理解でいいのでしょうか? 別に約束事では有りませんが、 MP_IWINDOW_SETVTBL(pVtbl, pfnEn, pfnRd, pfnHE, pfnDel); という使い方を意識している為でしょう。 最後に「;」をつけると呼び出しは MP_IWINDOW_SETVTBL(pVtbl, pfnEn, pfnRd, pfnHE, pfnDel) になってしまい、ここで終っているのかどうか分かりにくくなります。 >(3) 似たような意味ですが、ブロックが異なるので、 ifが2つ重なった場合など、ブロック演算子ありとなしで 動きが変わったりするので使い方に気をつけなければ行けません。 >(4) QINTERFACEがどの様なものなのかによりますが見た目は、 「値を返さずIWindow型ポインタを引数に持つ関数へのポインタ変数」 Deleteを宣言しているように見えます。
お礼
aris-wizさんありがとうございます! jactaさんのと併せて読むと、 大変勉強になります! MP_IWINDOW_SETVTBL(pVtbl, pfnEn, pfnRd, pfnHE, pfnDel); の部分もすごく参考になりました! みんなすごいな…しみじみ…
- php504
- ベストアンサー率42% (926/2160)
void (*Delete)(IWindow * po); これは関数ポインタです。 関数の名前も内部ではポインタとして扱われています。 下の例ではprint_addという関数とprint_subという関数を定義していますが main関数ではfuncという関数ポインタを使って定義した関数を呼び出しています。 #include <stdio.h> void print_add(int a, int b) { printf("%d\n", a+b); } void print_sub(int a, int b) { printf("%d\n", a-b); } int main(void) { void (*func)(int a, int b); func = print_add; func(1, 2); // print_add(1, 2)が呼ばれ3が表示 func = print_sub; func(1, 2); // print_sub(1, 2)が呼ばれ-1が表示 return 0; }
お礼
なるほど!! 関数の名前も、ポインターなんですね! 例題、すごくよく分かりました。 ありがとうございます。
- asuncion
- ベストアンサー率33% (2127/6289)
#2の者です。 仮に、 void Delete(IWindow * po); と書くと、DeleteはIWindow *型の変数を受取って戻り値を返さない関数です。 しかし、関数名の頭に*を付けることで状況が一変します。 void *Delete(IWindow * po); と書くことで、先に説明したとおりDeleteはポインターを返します。 そして、型が任意ですので、何型へのポインターにするかはDeleteを 呼び出す側の責任となります。例えば、 char *p; p = Delete(IWindow * po); としたり、 int *q; q = Delete(IWindow * po); としたり、といった具合です。
お礼
asuncionさん、何度もありがとうございます! 上手く言えないのですが、 分かったような気がします^^; voidって、型が任意ってことなんですね! 戻り値を返さないっていう以外の意味があるんですね! ふむむ、あってんのかな… とにかく、C言語ってえらく難しいのですね>< コーヒー飲む回数が増えそうです…
- jacta
- ベストアンサー率26% (845/3158)
> voidをカッコで囲んでいるのは > void型にキャストしているという意味で合っていますか? はい。 こうしておかないと、間違った使い方を許してしまいます。
お礼
返事が遅れてしまいすいません。 了解しました! ありがとうございます。
- asuncion
- ベストアンサー率33% (2127/6289)
少しだけフォロー。 >void (*Delete)(IWindow * po); >の部分は、どういう風に理解すればいいのでしょうか? Deleteは、IWindow *型の変数を受取って戻り値を返さない関数へのポインターです。 (*Delete) の前後のカッコを外して void *Delete(IWindow * po); と書くと、 Deleteは、IWindow *型の変数を受取って任意型へのポインターを返す関数 となり、意味が全く変わってしまいます。
補足
asuncion様、何か先ほどもお世話になった気が^^; で、たぶん、すごくいいこと書いていただいたと思うので、 慎重に読んでみたのですが、 頭がだんだんオーバーヒートしてきて、 たった今、コーヒー淹れてきました! ちょっとクールダウン… >Deleteは、IWindow *型の変数を受取って >任意型へのポインターを返す関数 えーと、ここが良く分かりません。 voidって戻り値がないよっていう意味では?? あ、もしや、 void *Delete(IWindow * po); って、Delete(IWindow * po)はvoid型ですが、 *が付いているので、そのアドレスを入れるようになるから、 結局ポインター返しちゃうって理解でいいのでしょうか? たびたびで恐縮ですが よろしくご教授の程お願い致しますm(__)m
補足
回答ありがとうございます! えーと、ちょっと質問させてください。 #define MP_IWINDOW_SETVTBL(pVtbl, pfnEn, pfnRd, pfnHE, pfnDel) \ ((void)( \ ((pVtbl)->Enable = (pfnEn)), \ ((pVtbl)->Redraw = (pfnRd)), \ ((pVtbl)->HandleEvent = (pfnHE)), \ ((pVtbl)->Delete = (pfnDel)) \ )) の部分ですが、 voidをカッコで囲んでいるのは void型にキャストしているという意味で合っていますか? 大変レベルの低い質問ばかりで恐縮ですが よろしくお願いいたします。