Просмотр расширенных макросов C - PullRequest
44 голосов
/ 12 июня 2009

Если я хочу развернуть макрос C, какие есть хорошие способы сделать это (помимо отслеживания его вручную)?

Например, GTK_WIDGET_SET_FLAGS, он использует макрос, который использует макрос, который использует макрос (или два) ...

Я хочу просто увидеть, как оно каким-то образом расширяется автоматически, вместо того, чтобы искать каждый макрос, каждый шаг пути.

UPDATE

Я пробовал cpp, но, похоже, он делал только первый проход

на:

GTK_WIDGET_SET_FLAGS(obj, 13)

Я расширил включаемый файл, а затем:

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

Это объясняется этим сообщением об ошибке, которое я получаю на stderr (при использовании -o имени файла)

gtk/gtkwidget.h:34:21: gdk/gdk.h: No such file or directory
gtk/gtkwidget.h:35:31: gtk/gtkaccelgroup.h: No such file or directory
gtk/gtkwidget.h:36:27: gtk/gtkobject.h: No such file or directory
gtk/gtkwidget.h:37:31: gtk/gtkadjustment.h: No such file or directory
gtk/gtkwidget.h:38:26: gtk/gtkstyle.h: No such file or directory
gtk/gtkwidget.h:39:29: gtk/gtksettings.h: No such file or directory
gtk/gtkwidget.h:40:21: atk/atk.h: No such file or directory

каталоги gtk, atk и gdk находятся в текущем рабочем каталоге, так как я могу разрешить cpp искать в нем?

Кстати, gcc -E дает точно такой же вывод, как cpp

Update2:

Проблема включенного пути решается с помощью gcc -E и передачи каталога include с опцией -I

Ответы [ 11 ]

57 голосов
/ 12 июня 2009

В зависимости от того, какой компилятор вы используете, должен быть способ увидеть код после того, как препроцессор (который выполняет расширение макроса, макросы вообще не известны компилятору).

С 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;
}
11 голосов
/ 12 июня 2009

В Visual Studio вы можете сгенерировать файл модуля перевода результата препроцессора. Вы можете перейти к параметрам проекта, C / C ++ / Preprocessor и поставить «Generate Preprocessed File» или «Preprocess to a File» на Yes (или использовать переключатель компилятора / P или / EP для включения номеров строк или нет).

9 голосов
/ 16 июля 2015

Вы можете вывести расширение макроса во время выполнения следующим образом:

#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 может помочь, но только если вы научите его всем используемым вами заголовкам и флагам компилятора.

4 голосов
/ 12 июня 2009
gcc -E myfile.c
3 голосов
/ 12 июня 2009

gcc даже с -E нужен путь к файлам заголовков ... как -I _path_to_your_headers ...

Если у вас есть Makefile, обычно вы можете переопределить CC с помощью gcc -E

Как правило, cpp - это всего лишь скрипт, добавляющий некоторые флаги в gcc для препроцессора, например, традиционный ...

3 голосов
/ 12 июня 2009

Многие IDE покажут вам расширенную версию макроса в редакторе, когда указатель мыши наведет курсор на идентификатор (или каким-либо другим способом). Я знаю, что Eclipse / CDT делает это, и Visual Studio делает это (по крайней мере, VS 2008).

Наличие компилятором сгенерированного предварительно обработанного вывода может быть полезно, если вы отслеживаете сложную проблему, но для повседневного использования, когда вы просто хотите узнать, что происходит с кодом на экране, использование IDE путь.

3 голосов
/ 12 июня 2009

Если вы используете gcc, вы также можете запустить

cpp myfile.c
2 голосов
/ 12 июня 2009

Попробуйте запустить cpp для вашего исходного файла

2 голосов
/ 12 июня 2009

Вы хотите запустить только этап препроцессора вашего компилятора, отвечающий за расширение макросов. Для gcc это "gcc -E", но я не уверен насчет других компиляторов.

1 голос
/ 12 июня 2009

Вы пытались запустить gcc -E несколько раз, пока не осталось макросов?

...