Просмотр расширенных макросов C
Если я хочу развернуть макрос C, каковы хорошие способы сделать это (помимо отслеживания его вручную)?
Например, GTK_WIDGET_SET_FLAGS
, он использует макрос, который использует макрос, который использует макрос (или два)...
Я хочу просто увидеть его каким-то образом автоматическим образом, вместо поиска каждого макроса на каждом шагу.
UPDATE
Я пробовал cpp, но, похоже, только первый проход
на
GTK_WIDGET_SET_FLAGS(obj, 13)
Я получил расширенный файл include, а затем:
G_STMT_START{ ((GTK_OBJECT_FLAGS (obj)) |= (13)); }G_STMT_END
Это объясняется этим сообщением об ошибке. Я получаю это на stderr (при использовании -o filename)
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?
btw, gcc -E
дает тот же самый результат, что и cpp
Update2:
Проблема с включенным путём решается с помощью gcc -E и передачи каталога include с опцией -I
Ответы
Ответ 1
В зависимости от того, какой компилятор вы используете, должен быть способ увидеть код после preprocessor (который расширяет макрос, макросы вообще не известны компилятору).
В 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;
}
Ответ 2
В Visual Studio вы можете сгенерировать исходный файл перевода с препроцессором. Вы можете перейти к вариантам проекта, C/С++/Preprocessor и поместить "Generate Preprocessed File" или "Preprocess to a File" в "Yes" (или использовать переключатель компилятора /P или/EP для включения номеров строк или нет).
Ответ 3
Вы можете сбросить расширение макроса во время выполнения следующим образом:
#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
gcc -E myfile.c
Ответ 5
Если вы используете gcc, вы также можете запустить
cpp myfile.c
Ответ 6
Многие IDE покажут вам расширенную версию макроса в редакторе, когда указатель мыши нависает над идентификатором (или каким-либо другим способом). Я знаю, что Eclipse/CDT делает это, и Visual Studio делает это (по крайней мере, VS 2008).
Наличие компилятора для генерации предварительно обработанного вывода может оказаться полезным, если вы отслеживаете сложную проблему, но для использования в режиме "день/день", когда вы просто хотите знать, что происходит с кодом на вашем экране, использование IDE путь.
Ответ 7
gcc даже с -E требуется путь к файлам заголовков... например -I_path_to_your_headers...
Если у вас есть Makefile, вообще-то, что вы можете сделать, это перехват CC с gcc -E
Как правило, cpp представляет собой только script, добавляя некоторые флаги в gcc для препроцессора, как традиционные...
Ответ 8
Вы хотите запустить только этап препроцессора своего компилятора, ответственный за расширение макросов. Для gcc
, это "gcc -E", но я не уверен в других компиляторах.
Ответ 9
Попробуйте запустить cpp в исходном файле
Ответ 10
Вы пытались запустить gcc -E несколько раз, пока не осталось больше макросов?
Ответ 11
Попав в ловушку отрывочной 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))
^
благодаря "mdematos" в http://MicroChip.com/forums/m724722.aspx