Kann gcc C-Code nach der Vorverarbeitung ausgeben?

Lesezeit: 6 Minuten

Benutzeravatar von LGTrader
LGTrader

Ich verwende eine Open-Source-Bibliothek, die viele Vorverarbeitungsanweisungen zu haben scheint, um viele andere Sprachen als C zu unterstützen. Damit ich studieren kann, was die Bibliothek tut, möchte ich den C-Code sehen, den ich nach der Vorverarbeitung kompiliere , mehr wie das, was ich schreiben würde.

Kann gcc (oder jedes andere in Linux allgemein verfügbare Tool) diese Bibliothek lesen, aber C-Code ausgeben, der die Vorverarbeitung in was auch immer konvertiert hat und auch von einem Menschen lesbar ist?

  • Der vorverarbeitete Code wird keine Präprozessoranweisungen mehr haben, aber ich bin mir ziemlich sicher, dass er viel weniger lesbar sein wird als vor der Vorverarbeitung …

    – Alex W

    5. Februar 2011 um 2:58 Uhr

  • @AlexW – Das kommt darauf an völlig wie schrecklich die Leute, die den Code geschrieben haben, den Präprozessor missbraucht haben.

    – Falscher Name

    6. September 2017 um 0:34 Uhr

  • Bitte erwägen Sie, Ihre akzeptierte Antwort hier zu ändern. gcc -E ist nützlicher, als die Zeile neu schreiben zu müssen, damit sie funktioniert cpp.

    – Grau

    27. März 2018 um 21:31 Uhr

  • Ciro hat sehr gut abgeschnitten gcc -save-temps Ich schlage vor, einen Blick darauf zu werfen.

    – Louis Go

    8. Dezember 2021 um 3:37 Uhr


Benutzeravatar von mipadi
mipadi

Ja. Übergeben Sie gcc die -E Möglichkeit. Dadurch wird vorverarbeiteter Quellcode ausgegeben.

  • Wenn Ihre Compiler-Befehle bereits einen Parameter wie -o something.o Sie können es auch ändern in -o something.i. Andernfalls befindet sich die vorverarbeitete Ausgabe in der .o Datei.

    – Tor Klingeberg

    19. März 2015 um 11:18 Uhr


  • @TorKlingberg Kann ich das für mehrere Dateien gleichzeitig tun?

    – Benutzer2808264

    18. September 2016 um 0:31 Uhr

  • @ user2808264 gcc -E file1.c file2.c ...

    – Matthias

    13. Dezember 2018 um 10:10 Uhr

  • Gibt es eine Option für den Präprozessor, nur Makros wie zu erweitern #define SIZE 1000 oder #ifdef Something #endif aber nicht #include <other_file.h> Ich möchte eine vorverarbeitete Datei sehen, aber ohne externe Funktionen, die in eine einzelne Datei importiert werden.

    – Quecksilber0114

    22. Oktober 2020 um 12:58 Uhr


Benutzeravatar von tpdi
tpdi

cpp ist der Präprozessor.

Laufen cpp filename.c um den vorverarbeiteten Code auszugeben oder besser in eine Datei umzuleiten mit
cpp filename.c > filename.preprocessed.

  • Ich denke, das ist die beste Antwort, weil es cpp direkt demonstriert. Linux-Systeme (zumindest Manjaro) scheinen standardmäßig auch -E zu haben. Ich erhalte in beiden Fällen die gleichen Ergebnisse von diesem Befehl. diff taucht kein Unterschied in den Dateien auf. Dies scheint auch eine nützliche Methode zu sein, um den Code vorzuverarbeiten und nach Fehlern in Ihren Makros zu suchen. Tolle Frage und tolle Antwort (IALCTHW).

    – lee8oi

    11. Dezember 2018 um 16:07 Uhr

  • @lee8oi Ich war neugierig, was IALCTHW bedeutet, aber mein Versuch, im Internet danach zu suchen, führte nur zu dieser Seite als Suchergebnis. Was bedeutet dieses Akronym? Ich bin ziemlich neugierig.

    – Benutzer64742

    19. März 2021 um 19:46 Uhr

Ciro Santilli Benutzeravatar von OurBigBook.com
Ciro Santilli OurBigBook.com

-save-temps

Dies ist eine weitere gute Option, die Sie im Hinterkopf behalten sollten:

gcc -save-temps -c -o main.o main.c

Haupt c

#define INC 1

int myfunc(int i) {
    return i + INC;
}

und jetzt neben der normalen Ausgabe main.oenthält das aktuelle Arbeitsverzeichnis außerdem die folgenden Dateien:

  • main.i ist die gewünschte vorbesessene Datei, die Folgendes enthält:

    # 1 "main.c"
    # 1 "<built-in>"
    # 1 "<command-line>"
    # 31 "<command-line>"
    # 1 "/usr/include/stdc-predef.h" 1 3 4
    # 32 "<command-line>" 2
    # 1 "main.c"
    
    
    int myfunc(int i) {
        return i + 1;
    }
    
  • main.s ist ein Bonus 🙂 und enthält die generierte Assembly:

        .file   "main.c"
        .text
        .globl  myfunc
        .type   myfunc, @function
    myfunc:
    .LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    %edi, -4(%rbp)
        movl    -4(%rbp), %eax
        addl    $1, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE0:
        .size   myfunc, .-myfunc
        .ident  "GCC: (Ubuntu 8.3.0-6ubuntu1) 8.3.0"
        .section    .note.GNU-stack,"",@progbits
    

Wenn Sie dies für eine große Anzahl von Dateien tun möchten, sollten Sie stattdessen Folgendes verwenden:

 -save-temps=obj

Dadurch werden die Zwischendateien im selben Verzeichnis wie die gespeichert -o Objektausgabe anstelle des aktuellen Arbeitsverzeichnisses, wodurch potenzielle Basisnamenkonflikte vermieden werden.

Der Vorteil dieser Option über -E ist, dass es einfach zu jedem Build-Skript hinzugefügt werden kann, ohne viel in den Build selbst einzugreifen.

Eine weitere coole Sache an dieser Option ist, wenn Sie hinzufügen -v:

gcc -save-temps -c -o main.o -v main.c

Es zeigt tatsächlich die expliziten Dateien, die anstelle von hässlichen temporären Dateien verwendet werden /tmpso ist es einfach, genau zu wissen, was vor sich geht, einschließlich der Vorverarbeitungs- / Kompilierungs- / Montageschritte:

/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu main.c -mtune=generic -march=x86-64 -fpch-preprocess -fstack-protector-strong -Wformat -Wformat-security -o main.i
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -fpreprocessed main.i -quiet -dumpbase main.c -mtune=generic -march=x86-64 -auxbase-strip main.o -version -fstack-protector-strong -Wformat -Wformat-security -o main.s
as -v --64 -o main.o main.s

Getestet in Ubuntu 19.04 amd64, GCC 8.3.0.

CMake vordefinierte Ziele

CMake stellt automatisch Ziele für die vorverarbeitete Datei bereit:

make help

zeigt uns, was wir können:

make main.i

und dieses Ziel läuft:

Preprocessing C source to CMakeFiles/main.dir/main.c.i
/usr/bin/cc    -E /home/ciro/bak/hello/main.c > CMakeFiles/main.dir/main.c.i

so kann die Datei unter eingesehen werden CMakeFiles/main.dir/main.c.i

Getestet auf cmake 3.16.1.

  • Viel eleganter als -E, da ich einfach -save-temps zu CFLAGS hinzufügen kann, ohne das Gesamtverhalten des Build-Skripts zu ändern. Vielen Dank!

    – EvertW

    22. Mai 2019 um 16:00 Uhr


  • Dies ist in der Tat sehr nützlich, und -E ist sehr praktisch für einzelne Dateien.

    – C–

    13. Juni 2019 um 5:04 Uhr

  • Unglaublich nützlich! Danke!

    – Pedro Pérez

    8. März um 15:10 Uhr

Benutzeravatar von Jack Ritter
Jack Ritter

Ich verwende gcc als Präprozessor (für HTML-Dateien). Es macht genau das, was Sie wollen. Es erweitert “#–“-Anweisungen und gibt dann eine lesbare Datei aus. (KEINER der anderen C/HTML-Präprozessoren, die ich ausprobiert habe, tut dies – sie verketten Zeilen, verschlucken Sonderzeichen usw.) Angenommen, Sie haben gcc installiert, lautet die Befehlszeile:

gcc -E -xc -P -C -traditional-cpp code_before.cpp > ​​code_after.cpp

(Muss nicht ‘cpp’ sein.) Es gibt eine ausgezeichnete Beschreibung dieser Verwendung unter http://www.cs.tut.fi/~jkorpela/html/cpre.html.

Das “-traditional-cpp” behält Leerzeichen und Tabulatoren bei.

Laufen:

gcc -E <file>.c

oder

g++ -E <file>.cpp

Benutzeravatar von Andy
Andy

Angenommen, wir haben eine Datei als Message.cpp oder eine .c-Datei

Schritte 1: Vorverarbeitung (Argument -E)

g++ -E .\Message.cpp > P1

Die generierte P1-Datei enthält erweiterte Makros, und Inhalte und Kommentare der Header-Datei werden entfernt.

Schritt 2: Vorverarbeitete Datei in Assembly übersetzen (Argument -S). Diese Aufgabe übernimmt der Compiler

g++ -S .\Message.cpp

Ein Assembler (ASM) wird generiert (Message.s). Es hat den ganzen Assembler-Code.

Schritt 3: Assemblercode in Objektcode übersetzen. Hinweis: Message.s wurde in Schritt 2 generiert.

g++ -c .\Message.s

Eine Objektdatei mit dem Namen Message.o wird generiert. Es ist die binäre Form.

Schritt 4: Verknüpfen der Objektdatei. Diese Aufgabe übernimmt der Linker

g++ .\Message.o -o MessageApp

Hier wird eine exe-Datei MessageApp.exe generiert.

#include <iostream>
using namespace std;

//This a sample program
int main()
{
  cout << "Hello" << endl;
  cout << PQR(P,K) ;
  getchar();
  return 0;
}

1423620cookie-checkKann gcc C-Code nach der Vorverarbeitung ausgeben?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy