VC PlusPlus:マクロ定義を展開した後のプログラムを確認する方法 新しいページはコチラ
提供: yonewiki
(ページの作成:「VC PlusPlusに戻る == '''概要''' == C++のプリプロセッサの記事で、マクロ定義の動きについて細かく説明しましたが、実際のマ...」) |
(→概要) |
||
1行: | 1行: | ||
[[VC PlusPlus]]に戻る | [[VC PlusPlus]]に戻る | ||
== '''概要''' == | == '''概要''' == | ||
− | C++ | + | C++のプリプロセッサ([[C プリプロセッサ]]、[[C マクロ]]、[[C プリプロセッサ演算子]]、[[C ディレクティブ]])の記事で、マクロ定義の動きについて細かく説明しましたが、実際のマクロ定義は複雑で、自分が説明した程度の知識では、全ての置き換えを元に戻せるとは限らないし、もっと複雑なことだったりします。もっと複雑な場合の展開になると創造力がないt難しいです。正直、展開疲れみたいなこともありえます。作った人は楽をしようと思って知恵を振り絞るだけですが、他人が読み解けるかどうかといえば、そうでもないということです。マクロ定義の中でマクロ定義をするという、わりかし深いマクロ定義も存在します。 |
+ | 例えばいかのようなマクロ定義だとどうでしょう? | ||
+ | |||
+ | <syntaxhighlight2 lang="Cpp"> | ||
+ | #define QT_MANGLE_NAMESPACE(name) name | ||
+ | |||
+ | #define Q_INIT_RESOURCE(name) \ | ||
+ | do { extern int QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); \ | ||
+ | QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); } while (false) | ||
+ | |||
+ | |||
+ | Q_INIT_RESOURCE(resource1); | ||
+ | Q_INIT_RESOURCE(resource2); | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | なんじゃこれーっ!ってなったひともいると思います。QtライブラリのQ_INIT_RESOURCEマクロは上記のような定義になっています。ややこしいよね。##はトークン結合演算子です。QInitResources_に引数nameがくっつく感じに変換されます。ようするに前置句がQInitResources_となる名前が作られるということです。\は複数行を一行としてみなすための意味です。 | ||
+ | |||
+ | |||
+ | じゃ、いったんそれで書き直して見ますか。 | ||
+ | |||
+ | <syntaxhighlight2 lang="Cpp"> | ||
+ | #define QT_MANGLE_NAMESPACE(name) name | ||
+ | |||
+ | #define Q_INIT_RESOURCE(name) \ | ||
+ | do { extern int QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); \ | ||
+ | QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); } while (false) | ||
+ | |||
+ | |||
+ | // Q_INIT_RESOURCE(resource1); | ||
+ | do { extern int QT_MANGLE_NAMESPACE(qInitResources_resource1) (); | ||
+ | QT_MANGLE_NAMESPACE(qInitResources_ resource2) (); } while (false) | ||
+ | |||
+ | // Q_INIT_RESOURCE(resource2); | ||
+ | do { extern int QT_MANGLE_NAMESPACE(qInitResources_resource1) (); | ||
+ | QT_MANGLE_NAMESPACE(qInitResources_ resource2) (); } while (false) | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | |||
+ | こうなりました。nameだったところにresource1というキーワードが入りました。マクロは引数一つで二つ以上の場所に展開できるので1行目と2行目両方がかわりました。そしたら。 | ||
+ | |||
+ | |||
+ | <syntaxhighlight2 lang="Cpp"> | ||
+ | #define QT_MANGLE_NAMESPACE(name) name | ||
+ | |||
+ | #define Q_INIT_RESOURCE(name) \ | ||
+ | do { extern int QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); \ | ||
+ | QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); } while (false) | ||
+ | |||
+ | |||
+ | // Q_INIT_RESOURCE(resource1); | ||
+ | do { extern int qInitResources_resource1(); | ||
+ | qInitResources_ resource1 (); } while (false) | ||
+ | |||
+ | // Q_INIT_RESOURCE(resource2); | ||
+ | do { extern int qInitResources_resource2(); | ||
+ | qInitResources_ resource2 (); } while (false) | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | となります。整理すると | ||
+ | |||
+ | <syntaxhighlight2 lang="Cpp"> | ||
+ | do { | ||
+ | extern int qInitResources_resource1(); | ||
+ | qInitResources_ resource1(); | ||
+ | }while(false) | ||
+ | |||
+ | do { | ||
+ | extern int qInitResources_resource2(); | ||
+ | qInitResources_ resource2(); | ||
+ | }while(false) | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | と同じです。externがついているので、このファイル以外のどこかで定義されて実体化されているかもしれない外側から呼び出しできるint型のqInitResources_resource1を使うことを宣言しています。それを引数無しで初期化しています。int型の場合は0になります。外から呼び出せる形式でかつ、ここで初期化したいというプログラムになっています。何個もこのような変数を生成するときには、このマクロは便利ですが、これをマクロでやっているということを紐解くのはなかなか手間のかかることだということが、わかったと思います。 | ||
[[VC PlusPlus]]に戻る | [[VC PlusPlus]]に戻る |