c c-preprocessor

Ver macros C expandidos



c-preprocessor (11)

Si quiero expandir una macro C, ¿cuáles son algunas buenas maneras de hacerlo (además de rastrearla manualmente)?

Por ejemplo, GTK_WIDGET_SET_FLAGS , usa una macro que usa una macro que usa una macro (o dos) ...

Quiero simplemente verlo de alguna manera expandido automágicamente, en lugar de buscar cada macro, en cada paso del camino.

ACTUALIZAR

Intenté cpp, pero parecía que solo hacía el primer pase

en:

GTK_WIDGET_SET_FLAGS(obj, 13)

Obtuve el archivo de inclusión expandido y luego:

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

Esto se explica por estos mensajes de error Obtengo esto en stderr (cuando se usa -o nombre de archivo)

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

los directorios gtk, atk y gdk están todos en el directorio de trabajo actual, entonces ¿cómo dejo que cpp busque en él?

Por cierto, gcc -E da el mismo resultado exacto que cpp

Actualización2:

El problema de la ruta de inclusión se resuelve mediante el uso de gcc -E y pasando el directorio de inclusión con la opción -I


¿Has intentado ejecutar gcc -E varias veces hasta que ya no hay macros?


Cuando está atrapado en un IDE incompleto, pruebe algo como

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

para producir

…/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)) ^

gracias a "mdematos" en http://MicroChip.com/forums/m724722.aspx


Dependiendo del compilador que use, debe haber una manera de ver el código después de que el preprocessor (que hace la expansión de macro, las macros no son conocidas por el compilador en absoluto) esté listo.

Con gcc, la opción es -E . Aquí hay un ejemplo simplificado, usando el código de juguete y no la macro GTK + real:

~/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; }


Desea ejecutar solo la etapa de preprocesador de su compilador, responsable de expandir las macros. Para gcc , eso es "gcc -E", pero no estoy seguro acerca de otros compiladores.


En Visual Studio, puede generar el archivo de la unidad de traducción resultante del preprocesador. Puede ir a las opciones de proyecto, C / C ++ / Preprocesador y poner "Generar archivo preprocesado" o "Preprocesar a un archivo" en Sí (o usar el modificador de compilador / P o / EP para incluir números de línea o no).


Intenta ejecutar cpp en tu archivo fuente


Muchos IDE le mostrarán la versión expandida de la macro en el editor cuando el puntero del mouse pase sobre el identificador (o de alguna otra manera). Sé que Eclipse / CDT hace esto, y Visual Studio hace esto (al menos VS 2008 lo hace).

Hacer que el compilador genere un resultado preprocesado puede ser útil si está rastreando un problema difícil, pero para el uso diario en el que solo quiere saber qué está sucediendo con el código en su pantalla, usar el IDE es la forma de ir.


Puede volcar la expansión de una macro en tiempo de ejecución como este:

#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; }

El programa imprime:

''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>)''

Sin embargo, esto solo produce la expansión completa . Si necesita pasos individuales, Eclipse / CDT puede ayudar, pero solo si le enseña todos los encabezados y banderas del compilador que utiliza.


Si usas gcc, también puedes ejecutar

cpp myfile.c


gcc incluso con -E necesita la ruta de los archivos de encabezado ... como -I_path_to_your_headers ...

Si tienes un Makefile, generalmente, lo que podrías hacer es dominar CC con gcc -E

En general, cpp es solo un script que agrega algunos indicadores a gcc para el preprocesador, como los tradicionales ...


gcc -E myfile.c