Wenn ich ein C-Makro erweitern möchte, wie kann man das machen (abgesehen von der manuellen Nachverfolgung)?
Zum Beispiel verwendet GTK_WIDGET_SET_FLAGS
ein Makro, das ein Makro verwendet, das ein Makro (oder zwei) verwendet ...
Ich möchte es nur irgendwie automatisiert sehen, anstatt nach jedem Makro, jedem Schritt des Weges zu suchen.
Ich habe cpp ausprobiert, aber es schien nur der erste Durchlauf zu sein
auf:
GTK_WIDGET_SET_FLAGS(obj, 13)
Ich habe die Include-Datei erweitert und dann:
G_STMT_START{ ((GTK_OBJECT_FLAGS (obj)) |= (13)); }G_STMT_END
Dies wird durch diese Fehlermeldung erklärt, die ich auf stderr bekomme (wenn -o Dateiname verwendet wird)
gtk/gtkwidget.h: 34: 21: gdk/gdk.h: Keine solche Datei oder ein solches Verzeichnis gtk/gtkwidget.h: 35: 31: gtk/gtkaccelgroup.h: Keine solche Datei oder ein solches Verzeichnis gtk/gtkwidget.h: 36: 27: gtk/gtkobject.h: Keine solche Datei oder ein solches Verzeichnis gtk/gtkwidget.h: 37: 31: gtk/gtkadjustment.h: Keine solche Datei oder ein solches Verzeichnis gtk /gtkwidget.h:38:26: gtk/gtkstyle.h: Keine solche Datei oder ein solches Verzeichnis gtk/gtkwidget.h: 39: 29: gtk/gtksettings.h: Keine solche Datei oder ein solches Verzeichnis gtk/gtkwidget .h: 40: 21: atk/atk.h: Keine solche Datei oder ein solches Verzeichnis
die Verzeichnisse gtk, atk und gdk befinden sich alle im aktuellen Arbeitsverzeichnis. Wie lasse ich cpp darin suchen?
Übrigens, gcc -E
liefert genau dieselbe Ausgabe wie cpp
Das Problem mit dem Include-Pfad wird gelöst, indem Sie gcc -E verwenden und das Include-Verzeichnis mit der Option -I übergeben
Abhängig davon, welchen Compiler Sie verwenden, sollte es möglich sein, den Code zu sehen, nachdem der Präprozessor (der die Makroerweiterung macht, Makros sind dem Compiler überhaupt nicht bekannt) erledigt ist.
Bei gcc ist die Option -E . Hier ist ein vereinfachtes Beispiel, das Spielzeugcode verwendet und nicht das eigentliche GTK + -Makro:
~/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;
}
In Visual Studio können Sie die aus einer Präprozessor-Datei resultierende Einheit erstellen. Sie können die Projektoptionen C/C++/Preprozessor aufrufen und "Vorverarbeitete Datei generieren" oder "Vorverarbeitung in eine Datei" auf "Ja" setzen (oder den Compiler-Schalter/P oder/EP verwenden, um Zeilennummern einzufügen oder nicht).
Sie können die Erweiterung eines Makros zur Laufzeit wie folgt sichern:
#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;
}
Das Programm druckt:
'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>)'
Dies ergibt jedoch nur die Erweiterung full . Wenn Sie einzelne Schritte benötigen, kann Eclipse/CDT helfen, jedoch nur, wenn Sie alle verwendeten Header und Compiler-Flags einlernen.
gcc -E myfile.c
Wenn Sie gcc verwenden, können Sie auch ausführen
cpp myfile.c
Viele IDEs zeigen Ihnen die erweiterte Version des Makros im Editor an, wenn der Mauszeiger über den Bezeichner (oder auf andere Weise) geführt wird. Ich weiß, dass Eclipse/CDT dies tut und Visual Studio dies (zumindest VS 2008).
Wenn der Compiler vorverarbeitete Ausgaben generiert, kann dies nützlich sein, wenn Sie ein schwieriges Problem aufspüren, aber Tag für Tag verwenden, wenn Sie einfach wissen möchten, was mit dem Code auf Ihrem Bildschirm geschieht, indem Sie die IDE ist der Weg zu gehen.
gcc selbst mit -E benötigt den Pfad der Headerdateien ... wie -I _path_to_your_headers ...
Wenn Sie ein Makefile haben, können Sie CC mit gcc -E übertreiben
Im Allgemeinen ist cpp nur ein Skript, das gcc für den Präprozessor einige Markierungen hinzufügt.
Sie möchten nur die Präprozessor - Stufe Ihres Compilers ausführen, der für die Erweiterung von Makros verantwortlich ist. Für gcc
ist das "gcc -E", aber ich bin nicht sicher, was andere Compiler angeht.
Führen Sie cpp für Ihre Quelldatei aus
Haben Sie gcc -E mehrmals ausgeführt, bis keine Makros mehr vorhanden sind?
Wenn Sie in einer skizzenhaften IDE gefangen sind, versuchen Sie Folgendes
#define DISPLAY_VALUE2(x) #x
#define DISPLAY_VALUE(x) DISPLAY_VALUE2(x)
#pragma message("#DEFINE F_CPU " DISPLAY_VALUE(F_CPU))
produzieren
…/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))
^
dank an "mdematos" unter http://MicroChip.com/forums/m724722.aspx