wake-up-neo.com

Erweiterte C-Makros sehen

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.

AKTUALISIEREN

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

Update2:

Das Problem mit dem Include-Pfad wird gelöst, indem Sie gcc -E verwenden und das Include-Verzeichnis mit der Option -I übergeben

43
hasen

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;
}
57
unwind

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

11

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.

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

Wenn Sie gcc verwenden, können Sie auch ausführen

cpp myfile.c
3
qrdl

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.

3
Michael Burr

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.

3
LB40

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.

2
Andrew Jaffe

Führen Sie cpp für Ihre Quelldatei aus

2
Alex Brown

Haben Sie gcc -E mehrmals ausgeführt, bis keine Makros mehr vorhanden sind?

1
Earlz

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

0
devon