VC PlusPlus:マクロ定義を展開した後のプログラムを確認する方法 新しいページはコチラ
提供: yonewiki
(→マクロ定義展開方法) |
(→概要) |
||
1行: | 1行: | ||
[[VC PlusPlus]]に戻る | [[VC PlusPlus]]に戻る | ||
== '''概要''' == | == '''概要''' == | ||
− | C++のプリプロセッサ([[C プリプロセッサ]]、[[C マクロ]]、[[C プリプロセッサ演算子]]、[[C ディレクティブ]]) | + | C++のプリプロセッサ([[C プリプロセッサ]]、[[C マクロ]]、[[C プリプロセッサ演算子]]、[[C ディレクティブ]])の記事で、マクロ定義の動きについて細かく説明しましたが、実際のマクロ定義は複雑で、自分が説明した内容が理解できていれば、展開はできるにしても、聞きかじった程度の知識では、全ての置き換えを元に戻せるとは限らないし、もっと複雑なことだったりします。もっと複雑な場合の展開になると創造力がないと難しいです。正直、展開疲れみたいなこともありえます。作った人は楽をしようと思って知恵を振り絞るだけですが、他人が読み解けるかどうかといえば、そうでもないということです。マクロ定義の中でマクロ定義をするという、わりかし深いマクロ定義も存在します。 |
− | + | 例えば以下のようなマクロ定義だとどうでしょう? | |
<syntaxhighlight2 lang="Cpp"> | <syntaxhighlight2 lang="Cpp"> | ||
32行: | 32行: | ||
// Q_INIT_RESOURCE(resource1); | // Q_INIT_RESOURCE(resource1); | ||
do { extern int QT_MANGLE_NAMESPACE(qInitResources_resource1) (); | do { extern int QT_MANGLE_NAMESPACE(qInitResources_resource1) (); | ||
− | QT_MANGLE_NAMESPACE( | + | QT_MANGLE_NAMESPACE(qInitResources_resource1) (); } while (false) |
// Q_INIT_RESOURCE(resource2); | // Q_INIT_RESOURCE(resource2); | ||
− | do { extern int QT_MANGLE_NAMESPACE( | + | do { extern int QT_MANGLE_NAMESPACE(qInitResources_resource2) (); |
− | QT_MANGLE_NAMESPACE( | + | QT_MANGLE_NAMESPACE(qInitResources_resource2) (); } while (false) |
</syntaxhighlight2> | </syntaxhighlight2> | ||
− | + | こうなりました。nameだったところにresource1というキーワードが入りました。マクロは引数一つで二つ以上の場所に展開できるので1行目と2行目両方がかわりました。そしたらQT_MANGLE_NAMESPACEの引数自体が、文字列として再定義されるだけの動きをするのがQT_MANGLE_NAMESPACEの部分なので、それを解読すると、 | |
53行: | 53行: | ||
// Q_INIT_RESOURCE(resource1); | // Q_INIT_RESOURCE(resource1); | ||
do { extern int qInitResources_resource1(); | do { extern int qInitResources_resource1(); | ||
− | + | qInitResources_resource1 (); } while (false) | |
// Q_INIT_RESOURCE(resource2); | // Q_INIT_RESOURCE(resource2); | ||
do { extern int qInitResources_resource2(); | do { extern int qInitResources_resource2(); | ||
− | + | qInitResources_resource2 (); } while (false) | |
</syntaxhighlight2> | </syntaxhighlight2> | ||
65行: | 65行: | ||
do { | do { | ||
extern int qInitResources_resource1(); | extern int qInitResources_resource1(); | ||
− | + | qInitResources_resource1(); | |
}while(false) | }while(false) | ||
do { | do { | ||
extern int qInitResources_resource2(); | extern int qInitResources_resource2(); | ||
− | + | qInitResources_resource2(); | |
}while(false) | }while(false) | ||
</syntaxhighlight2> | </syntaxhighlight2> | ||
77行: | 77行: | ||
− | + | こういうことを機械的に確認する術があります。知らないよりは知っていた方が良いかもです。かなり深いプリプロッセッサになっている場合はコンパイルにもの凄く時間がかかりますが、ちょっとの我慢です。 | |
===''' マクロ定義展開方法 '''=== | ===''' マクロ定義展開方法 '''=== | ||
− | + | VisualStudioの特定のcppファイルのプロパティを変更することでプリプロセッサ処理後のプログラムを吐き出すことが出来ます。併せて、インクルードされているすべての変数、関数、クラス宣言が掌握できます。 | |
118行: | 118行: | ||
− | これで出力object(*.obj)ファイルが出力されるフォルダと同じ階層に*.iという名前で前処理の結果が出力されます。object(*.obj) | + | これで出力object(*.obj)ファイルが出力されるフォルダと同じ階層に*.iという名前で前処理の結果が出力されます。object(*.obj)ファイルは生成されません。先ほども記述しましたが、展開された部分を探すのに疲れる場合もあるかもしれませんが、マクロ展開された部分は必ずあります。根気よく検索で探しましょう。探しきれない場合は一度、かなりユニークな文字列の引数をマクロに設定して試すとよいかもしれません。先ほどの出力エディタに表示するのとは異なる内容で、展開中にファイルを行き来するので、ファイルの途中でのファイル離脱時は、その行番号を、行先の行番号とファイル名が表示されます。より、わかりやすいですが、単純に行ったり来たりすることもあるので、冗長に感じる場合もあります。あー、展開処理に満足したら、設定は最初の状態に戻しておいてくださいね。 |
124行: | 124行: | ||
− | 知ってると知らないとでは差がでるところの知識かなと思います。この便利な手法については誰も教えてくれないので、右も左もわからないで、この文章に巡り合えた人は'''ついている'''と思っていいでしょう。 | + | 知ってると知らないとでは差がでるところの知識かなと思います。この便利な手法については誰も教えてくれないので、右も左もわからないで、この文章に巡り合えた人は'''<span style="color: darkred;">ついている</span>'''と思っていいでしょう。 |
[[VC PlusPlus]]に戻る | [[VC PlusPlus]]に戻る |