web-dev-qa-db-ja.com

拡張されたCマクロを見る

Cマクロを拡張したい場合、それを行ういくつかの良い方法は何ですか(手動でトレースする以外に)?

例えば、 GTK_WIDGET_SET_FLAGS、マクロ(または2つ)を使用するマクロを使用するマクロを使用します...

すべてのマクロ、方法のすべてのステップを検索するのではなく、何らかの方法で自動的に展開されるのを見てみたいです。

更新

私はcppを試しましたが、最初のパスのみを行うようでした

オン:

GTK_WIDGET_SET_FLAGS(obj, 13)

インクルードファイルを展開し、次に:

G_STMT_START{ ((GTK_OBJECT_FLAGS (obj)) |= (13)); }G_STMT_END

これは、これらのエラーメッセージによって説明されます(stderrでこれを取得します(-o filenameを使用する場合))

 gtk/gtkwidget.h:34:21:gdk/gdk.h:そのようなファイルまたはディレクトリはありません
 gtk/gtkwidget.h:35:31:gtk/gtkaccelgroup.h:そのようなファイルはありませんまたはディレクトリ
 gtk/gtkwidget.h:36:27:gtk/gtkobject.h:そのようなファイルまたはディレクトリなし
 gtk/gtkwidget.h:37:31:gtk/gtkadjustment.h:いいえそのようなファイルまたはディレクトリ
 gtk/gtkwidget.h:38:26:gtk/gtkstyle.h:そのようなファイルまたはディレクトリなし
 gtk/gtkwidget.h:39:29:gtk/gtksettings.h :そのようなファイルまたはディレクトリはありません
 gtk/gtkwidget.h:40:21:atk/atk.h:そのようなファイルまたはディレクトリはありません

gtk、atk、およびgdkディレクトリはすべて現在の作業ディレクトリにあるので、cppで検索するにはどうすればよいですか?

ところで、gcc -Eは、cppとまったく同じ出力を提供します

Update2:

インクルードパスの問題は、gcc -Eを使用し、-Iオプションでインクルードディレクトリを渡すことで解決されます。

46
hasen

使用するコンパイラに応じて、 プリプロセッサ (マクロ展開を行い、マクロはコンパイラによってまったく認識されません)が実行された後にコードを確認する方法が必要です。

Gccの場合、オプションは -E です。以下は、実際のGTK +マクロではなく、おもちゃのコードを使用した簡単な例です。

~/tmp> cat cpptest.c
#define SET_FLAGS(w, f) ((w)->flags |= (f))

int main(void)
{
        SET_FLAGS(0, 4711);

        return 0;
}
~/tmp> gcc -E cpptest.c
# 1 "cpptest.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "cpptest.c"


int main(void)
{
 ((0)->flags |= (4711));

 return 0;
}
60
unwind

Visual Studioでは、プリプロセッサ結果の翻訳単位ファイルを生成できます。プロジェクトオプション、C/C++/Preprocessorに移動して、「Generate Preprocessed File」または「Preprocess to a File」をYesに設定します(または/ Pまたは/ EPコンパイラスイッチを使用して行番号を含めるかどうかを指定します)。

13

次のように、実行時にマクロの展開をダンプできます。

#include <stdio.h>

/*
 * generic helper macros
 */
#define CALL(macro, arguments) macro arguments
#define STR(...) STR_(__VA_ARGS__)
#define STR_(...) # __VA_ARGS__

/*
 * dumps a macro and its expansion to stdout
 * the second argument is optional and specifies the number of
 * arguments that macro takes: 0 means macro takes zero arguments
 * no second argument means macro is not function-like
 */
#define DUMP_MACRO(macro, ...) \
    do { \
        puts ( \
            "'" \
            # macro STR(DUMP_MACRO_ARGS_ ## __VA_ARGS__) \
            "' expands to '" \
            STR(CALL(macro, DUMP_MACRO_ARGS_ ## __VA_ARGS__)) \
            "'" \
        ); \
    } while (0)
/* helpers for DUMP_MACRO, add more if required */
#define DUMP_MACRO_ARGS_
#define DUMP_MACRO_ARGS_0 ()
#define DUMP_MACRO_ARGS_1 (<1>)
#define DUMP_MACRO_ARGS_2 (<1>, <2>)
#define DUMP_MACRO_ARGS_3 (<1>, <2>, <3>)

/*
 * macros to be used in examples for DUMP_MACRO
 */
#define EXAMPLE ( EXAMPLE0() << 9 )
#define EXAMPLE0() __GNUC__
#define EXAMPLE1(EXAMPLE1) EXAMPLE1
#define EXAMPLE3(EXAMPLE1, _, __) ( EXAMPLE1 ? _(__) : false )

int main() {
    /* examples */
    DUMP_MACRO(EXAMPLE);
    DUMP_MACRO(EXAMPLE0, 0);
    DUMP_MACRO(EXAMPLE1, 1);
    DUMP_MACRO(EXAMPLE3, 3);
    DUMP_MACRO(EXAMPLE3(EXAMPLE, EXAMPLE1, non_macro_symbol));
    /* does not work for DUMP_MACRO itself, because the
       preprocessor does not allow recursion */
    DUMP_MACRO(DUMP_MACRO, 1);
    DUMP_MACRO(DUMP_MACRO, 2);
    return 0;
}

プログラムは以下を印刷します。

'EXAMPLE' expands to '( 4 << 9 )'
'EXAMPLE0()' expands to '4'
'EXAMPLE1(<1>)' expands to '<1>'
'EXAMPLE3(<1>, <2>, <3>)' expands to '( <1> ? <2>(<3>) : false )'
'EXAMPLE3(EXAMPLE, EXAMPLE1, non_macro_symbol)' expands to '( ( 4 << 9 ) ? non_macro_symbol : false )'
'DUMP_MACRO(<1>)' expands to 'DUMP_MACRO (<1>)'
'DUMP_MACRO(<1>, <2>)' expands to 'DUMP_MACRO (<1>, <2>)'

ただし、これはfull展開のみを生成します。単一の手順が必要な場合、Eclipse/CDTが役立ちますが、使用するすべてのヘッダーとコンパイラフラグを教える場合のみです。

9
not-a-user
gcc -E myfile.c
4
Markus Schnell

Gccを使用する場合は、次も実行できます。

cpp myfile.c
3
qrdl

多くのIDEでは、マウスポインターが識別子の上に移動すると(または他の方法で)、エディターでマクロの拡張バージョンが表示されます。 Eclipse/CDTがこれを行い、Visual Studioがこれを行うことを知っています(少なくともVS 2008が行います)。

コンパイラに前処理された出力を生成させることは、トリッキーな問題を追跡している場合に役立ちますが、日中/日中にIDEが道です。

3
Michael Burr

-Eを使用してもgccはヘッダーファイルのパスを必要とします... -I _path_to_your_headers ...のように.

Makefileを持っている場合、一般に、gcc -EでCCをオーバーライドすることができます

一般的に、cppは、従来のように、プリプロセッサのgccにいくつかのフラグを追加するスクリプトにすぎません...

3
LB40

マクロを展開するコンパイラのpreprocessorステージのみを実行する必要があります。 gccの場合、これは「gcc -E」ですが、他のコンパイラについてはわかりません。

2
Andrew Jaffe

ソースファイルでcppを実行してみてください

2
Alex Brown

マクロがなくなるまでgcc -Eを複数回実行しようとしましたか?

1
Earlz

大ざっぱなIDEに閉じ込められたら、次のようなものを試してください

#define DISPLAY_VALUE2(x) #x
#define DISPLAY_VALUE(x) DISPLAY_VALUE2(x)
#pragma message("#DEFINE F_CPU " DISPLAY_VALUE(F_CPU))

生産する

…/sketch_may21a.ino: In function 'void loop()':
…/sketch_may21a.ino:10:54: note: #pragma message: #DEFINE F_CPU 16000000L
#pragma message("#DEFINE F_CPU " DISPLAY_VALUE(F_CPU))
                                                     ^

http://MicroChip.com/forums/m724722.aspx の「mdematos」に感謝

0
devon