• ベストアンサー

#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

質問者が選んだベストアンサー

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答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); > の部分は、どういう風に理解すればいいのでしょうか? 関数へのポインタです。

micchicchi
質問者

補足

回答ありがとうございます! えーと、ちょっと質問させてください。 #define MP_IWINDOW_SETVTBL(pVtbl, pfnEn, pfnRd, pfnHE, pfnDel) \   ((void)( \   ((pVtbl)->Enable = (pfnEn)), \   ((pVtbl)->Redraw = (pfnRd)), \   ((pVtbl)->HandleEvent = (pfnHE)), \   ((pVtbl)->Delete = (pfnDel)) \   )) の部分ですが、 voidをカッコで囲んでいるのは void型にキャストしているという意味で合っていますか? 大変レベルの低い質問ばかりで恐縮ですが よろしくお願いいたします。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (5)

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答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を宣言しているように見えます。

micchicchi
質問者

お礼

aris-wizさんありがとうございます! jactaさんのと併せて読むと、 大変勉強になります! MP_IWINDOW_SETVTBL(pVtbl, pfnEn, pfnRd, pfnHE, pfnDel); の部分もすごく参考になりました! みんなすごいな…しみじみ…

全文を見る
すると、全ての回答が全文表示されます。
  • php504
  • ベストアンサー率42% (926/2160)
回答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; }

micchicchi
質問者

お礼

なるほど!! 関数の名前も、ポインターなんですね! 例題、すごくよく分かりました。 ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。
  • asuncion
  • ベストアンサー率33% (2126/6288)
回答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); としたり、といった具合です。

micchicchi
質問者

お礼

asuncionさん、何度もありがとうございます! 上手く言えないのですが、 分かったような気がします^^; voidって、型が任意ってことなんですね! 戻り値を返さないっていう以外の意味があるんですね! ふむむ、あってんのかな… とにかく、C言語ってえらく難しいのですね>< コーヒー飲む回数が増えそうです…

全文を見る
すると、全ての回答が全文表示されます。
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

> voidをカッコで囲んでいるのは > void型にキャストしているという意味で合っていますか? はい。 こうしておかないと、間違った使い方を許してしまいます。

micchicchi
質問者

お礼

返事が遅れてしまいすいません。 了解しました! ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。
  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.2

少しだけフォロー。 >void (*Delete)(IWindow * po); >の部分は、どういう風に理解すればいいのでしょうか? Deleteは、IWindow *型の変数を受取って戻り値を返さない関数へのポインターです。 (*Delete) の前後のカッコを外して void *Delete(IWindow * po); と書くと、 Deleteは、IWindow *型の変数を受取って任意型へのポインターを返す関数 となり、意味が全く変わってしまいます。

micchicchi
質問者

補足

asuncion様、何か先ほどもお世話になった気が^^; で、たぶん、すごくいいこと書いていただいたと思うので、 慎重に読んでみたのですが、 頭がだんだんオーバーヒートしてきて、 たった今、コーヒー淹れてきました! ちょっとクールダウン… >Deleteは、IWindow *型の変数を受取って >任意型へのポインターを返す関数 えーと、ここが良く分かりません。 voidって戻り値がないよっていう意味では?? あ、もしや、 void *Delete(IWindow * po); って、Delete(IWindow * po)はvoid型ですが、 *が付いているので、そのアドレスを入れるようになるから、 結局ポインター返しちゃうって理解でいいのでしょうか? たびたびで恐縮ですが よろしくご教授の程お願い致しますm(__)m

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • #defineについて

    #define STATIC_ASSERT(expr) { \ char __STATIC_ASSERTION[(expr) ? 1 : -1]; \ (void)__STATIC_ASSERTION; \ } /* 符号付き整数の右シフトが算術シフトかどうか */ #define SHIFT_LEFT_SINGNED_USES_SAL \ (((signed int)0xffffffff >> 1) == 0xffffffff) /* 符号無し整数の右シフトが論理シフトかどうか */ #define SHIFT_LEFT_UNSIGNED_USES_SHL \ (((unsigned int)0xffffffff >> 1) == 0x7fffffff) とは一体どういう意味なのでしょうか? なぜ、ブロックの中にchar型が宣言されているのでしょうか? なぜ、(void)とキャストされているのでしょうか? できたらわかりやすくご教授よろしくお願いします。

  • C++ クラス名の前のdefine

    C++ クラス名の前のdefine 初めまして、質問させてください。 C++の作法?でクラス宣言時にクラス名の前につけるdefineには なんお意味があるのでしょうか? コード例 #define DEFINE class DEFINE Hoge{ }; 以上になります。 ご教授宜しくお願い致します。

  • javaの基本的な質問

    java初心者です。 サンプルプログラム等の宣言部分が下記の2通りで記載されていることがありますが、 カギ括弧の位置が違うこの2つは何か意味があるのでしょうか? それとも同じ意味ですか? ----------------------------------------- public static void main (String args[]) public static void main (String[] args) ----------------------------------------- よろしくお願いします。

    • ベストアンサー
    • Java
  • 解説をお願いします。

    #define ast_test_flag(p,flag) ({ \ typeof ((p)->flags) __p = (p)->flags; \ typeof (__unsigned_int_flags_dummy) __x = 0; \ (void) (&__p == &__x); \ ((p)->flags & (flag)); \ }) あるソースコードを読んでいると上のような記述に当たりました。 何をしているのか解説していただけませんか。 __xとか¥記号とか宣言していないものも多く、皆目見当がつきません。

  • (続)エラー「invalid conversion from `void (*)()' to `void (*)(int)'」

    お手数をお掛けしています。 > die の宣言を > void die(int sig); > にしたのであれば, session_loop の中で die を呼出すときにも引数は必要ですよ. > また, 最後の die の定義のところでも引数を取るようにしていますよね? ←念の為. えーと、下記のように static void die(int); : (中略) : signal(SIGINT, die(1)); : (中略) : /* 端末属性を復旧して終わる */ die(1); } : (中略) : static void die(int) { endwin(); /* 端末属性の復旧 */ exit(0); } としてみたのですが $g++ -o server server.c server.c: function 内の `void session_init(int, char, int, int, char, int, int)': server.c:134: void の値が本来の意味通りに無視されませんでした となってしまいました。 何か勘違いしてますでしょうか??

  • staticと+=の意味を・・・

    いろいろ調べたのですが、staticはクラスフィールドやクラスメソッドの宣言などに使うと書いてありますが、public static void mainとか以外に見たことありませんし使ったこともないんです・・・。 なのでイマイチ理解できません・・・。使い方を教えてください。あと、+=加算代入と書いてありますが、これもよくわかりません・・・。 なんか一語一語「これってどういう意味なんだろう?」とかって思うと調べても漠然とした説明ばかりで理解に苦しみます。 なにかいいアドバイスがあれば教えてください。よろしくお願いします。

    • ベストアンサー
    • Java
  • #define F_CPU という設定

    現在Atmel Studio6.1 + JTAGICE3でATmega88Pのプログラミングを行っています。 https://sourceforge.jp/projects/cc1101driver/scm/svn/tree/head/branches/test002_AVRS6_20140819/test02/ このプロジェクト内で、リアルタイムデバッグを行っているソースコードで、無線モジュールIC CC1101がある端末出力されて受信したデータがあった場合、SPI通信でATmega88PマイコンにSPI通信割り込みでデータを送信して、データ内容で条件が適合するとAtmega88pの特定のeepromアドレスへ受信データ内容の一部データ(IDコード)を書き込むようにしている箇所があります。 u8 setup_oper() 関数内の length = cc1101_rx((u8 *)fifo,0); if(length > 0) { gggLength = length; if(length == sizeof(fifo_t) && fifo-                        ・・・・(中略)・・・・ } リアルタイムデバッグ中に上記のコードで端末側がデータ送信を行っているのに、受信した場合にlength = cc1101_rx((u8 *)fifo,0); のコード部分では受信したデータのlength値が代入されるはずなのですが、それが”0”のままであるため、eepromへの書き込みが行われていないことに気づきました。 いろいろとソースコードの修正を試みたところ、 #define F_CPU 800000UL 元々このように設定されていたコードを #define F_CPU 2000000UL このように変更したところ、正常にCC1101からのSPI通信もeepromへのデータ書き込みもうまくいくことがわかりました。 この”#define F_CPU”というコードはどのような意味があるのかご教示頂きますよう、よろしくお願い致します。 また、現在Atmega88pの元周波数は8MHzを使用したく、8CKDIVのチェックを外しています。 なので、 #define F_CPU 8000000UL このように設定してみたところ、これだとCC1101とのSPI通信ができないようでeeprom書き込みのコードに到達できなくなります。 #define F_CPU 2000000UL これは内部周波数が元の8MHzを4分周した2MHzのことなのだろうか? このように思って2000000ULとしてみたのですが、この考えでよろしいのでしょうか? どうぞ、ご教示頂き増増すよう、よろしくお願い致します。

  • staticなフィールドをstaticじゃないメソッドで使うには?

    いつもお世話になっています。よろしくお願いします。 javaで、staticなメインメソッドからも、staticじゃないメソッドからも1つの メンバ変数(フィールド)を処理したいと思います。 private static String nr; というフィールドを宣言しました。 (staticであるmainメソッドの中で使えるようにstaticで宣言しようと思いました。) 次に、 private void Kensaku() { このstaticではないメソッドの中でString nrを使って処理を行いたいです。 } 初歩の初歩なことを質問してすみませんが、調べても分かりませんでした。 どうか、よろしくお願いします。

    • ベストアンサー
    • Java
  • ポインターがさっぱりです><

    C言語歴約2週間なのですが、 関数を見ていてさっぱりなので、3点ほど教えて下さい>< (1)CMediaPlayer * pme = (CMediaPlayer *)pi; pmeは、CMediaPlayer型のアドレスを入れる変数だと思うのですが、 正しいでしょうか? また、この部分、何で CMediaPlayer *pme のようにくっつけて書いてないのでしょうか? さらに、 (CMediaPlayer *)piは、一体何なのでしょう?@@; 特にこのカッコが良く分かりません… (2)AEEApplet_New(sizeof(CMediaPlayer), ClsId, pIShell,po,(IApplet**)ppObj,(AEEHANDLER)CMediaPlayer_HandleEvent,(PFNFREEAPPDATA)CMediaPlayer_FreeAppData)); (IApplet**)ppObj<この部分が分かりません。 これも(1)に似ているカッコの付き方なのですが、 **が2つあり、 これは何なのでしょう? (3)CMediaPlayer_CreateInstance(AEECLSID ClsId,IShell * pIShell,IModule * po,void ** ppObj); ここの、void ** ppObjの部分は、 (2)と似ていますが、 何故カッコがないのでしょうか? 文法的な質問ばかりなのですが、 ぜひよろしくお願い致します。

  • WEBカメラの動画制御を動的配列で、、

    先日「WEBカメラの画像を一定時間溜め込んで、    任意のタイミングで出力するプログラムのメモリ領域の    確保」に関して質問した者です。2次元配列を当初グローバルに宣言したところ、速度が遅くなってしまったため、動的に宣言したところ目標の速度を達成しました。 しかし停止時に例外が出てしまい、何度もプログラムを繰り返しているとどんどん速度が遅くなってしまいます。 原因を探っておりますがわかりません。 プログラムの変更箇所(動的配列の宣言部)を載せました。 これ以外のところは遅くとも正常に動作していた時と同様です。 例外の具体的な内容を明日にでもアップします。 情報不十分かもしれませんが、明らかな不具合等ありましたら、 お教えいただけますでしょうか? -ーーーーーーーーーーーーーーーーーーーーーーーー #define FRAMES 200 #define WX 640 #define WY 480 //int array[FRAMES][WX*WY]; グローバル宣言時のもの void Main(void) { int **array; array = new int*[FRAMES]; for(int i=0;i<FRAMES+1;i++){ array[i] = new int[WX*WY]; } //array[FRAMES][WX*WY]溜め込んで、     //任意のタイミングでディスプレイに出力します。 if(STOP) goto fin; } fin: for(int i=0;i<FRAMES+1;i++){ delete[] latesc[i]; } delete[] latesc; }