![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
表題の件ですが、
プログラム読んでいて分からないことありましたので、
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
No.1ベストアンサー
- 回答日時:
質問(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);
> の部分は、どういう風に理解すればいいのでしょうか?
関数へのポインタです。
この回答への補足
回答ありがとうございます!
えーと、ちょっと質問させてください。
#define MP_IWINDOW_SETVTBL(pVtbl, pfnEn, pfnRd, pfnHE, pfnDel) \
((void)( \
((pVtbl)->Enable = (pfnEn)), \
((pVtbl)->Redraw = (pfnRd)), \
((pVtbl)->HandleEvent = (pfnHE)), \
((pVtbl)->Delete = (pfnDel)) \
))
の部分ですが、
voidをカッコで囲んでいるのは
void型にキャストしているという意味で合っていますか?
大変レベルの低い質問ばかりで恐縮ですが
よろしくお願いいたします。
No.6
- 回答日時:
>(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);
の部分もすごく参考になりました!
みんなすごいな…しみじみ…
No.5
- 回答日時:
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;
}
No.4
- 回答日時:
#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言語ってえらく難しいのですね><
コーヒー飲む回数が増えそうです…
No.2
- 回答日時:
少しだけフォロー。
>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
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) Arduino UNO のC言語 2 2023/04/18 19:42
- C言語・C++・C# 質問です 下記のコードを分かりやすく解説お願いします 初心者です #include ‹stdio.h 3 2022/05/26 22:03
- 英語 Osteogenesis in group B and C were significantly l 2 2022/03/24 05:27
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- JavaScript オブジェクトから任意のプロパティを全て抽出する一番簡単な方法 1 2023/08/09 21:13
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# C言語:数値の桁数指定についての質問です。 8 2022/05/26 23:53
- その他(ゲーム) ドラクエで言う、賢さやMPが無くても繰り出せる遠距離攻撃(飛び道具)について。 1 2023/03/28 04:15
- Java java final 1 2022/06/10 22:49
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
【gcc・cygwin】multiple defin...
-
既定のコンストラクタがありま...
-
C++にてtemplateで受け取った任...
-
gcc: incompatible pointer type
-
戻り値を返す関数の前に(void)...
-
DLLの関数呼び出しで引数がある...
-
プログラミング教えてください
-
静的でないメンバ関数の呼び出...
-
【VC++6.0】イベントハンドラ関...
-
C# KeyDownイベントでショート...
-
DirectInput でのエラー
-
[Visual C++ 6.0] コンパイル(...
-
ウインドウの移動禁止
-
PowerShellにてツリービュー入...
-
C/C++でのScene管理について
-
(void)0 はどんな意味ですか
-
int main()、void main()、void...
-
マルチメディアタイマー
-
H8/3052について
-
_beginthread()の使用について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
既定のコンストラクタがありま...
-
【gcc・cygwin】multiple defin...
-
Notepad++の関数リスト表示の変...
-
戻り値を返す関数の前に(void)...
-
ArduinoでMouse関数を使用して...
-
C++にてtemplateで受け取った任...
-
int main()、void main()、void...
-
多重定義が起きている?--lnk20...
-
C# KeyDownイベントでショート...
-
静的でないメンバ関数の呼び出...
-
VC++でGetKeyboardStateがうま...
-
C# Controls.Addで動的に配置し...
-
gcc: incompatible pointer type
-
void*型の配列について
-
const_castのつかいどころを教...
-
C言語 ① 5秒間 1秒間隔で点滅を...
-
(void)0 はどんな意味ですか
-
TimerProc コールバック関数を...
-
H8マイコンのシリアル通信につ...
-
DLLの関数呼び出しで引数がある...
おすすめ情報