Dapatkah gcc mengeluarkan kode C setelah pemrosesan awal?


105

Saya menggunakan pustaka sumber terbuka yang tampaknya memiliki banyak arahan praproses untuk mendukung banyak bahasa selain C. Agar saya dapat mempelajari apa yang dilakukan pustaka tersebut, saya ingin melihat kode C yang saya kompilasi setelah praproses , lebih seperti yang saya tulis.

Dapatkah gcc (atau alat lain yang umumnya tersedia di Linux) membaca pustaka ini tetapi mengeluarkan kode C yang memiliki pra-pemrosesan diubah menjadi apa pun dan juga dapat dibaca oleh manusia?


Kode yang telah diproses sebelumnya tidak akan memiliki arahan preprocessor lagi tetapi saya cukup yakin itu akan jauh lebih sulit dibaca daripada sebelum diproses sebelumnya ...
Alex W

2
@AlexW - Itu sepenuhnya bergantung pada seberapa mengerikan orang yang menulis kode menyalahgunakan preprocessor.
Nama Palsu

1
Harap pertimbangkan untuk mengubah jawaban Anda yang diterima di sini. gcc -Elebih berguna daripada harus menulis ulang baris untuk membuatnya berfungsi cpp.
Gray

Jawaban:


194

Iya. Berikan -Eopsi gcc . Ini akan mengeluarkan kode sumber yang telah diproses sebelumnya.


12
Jika perintah kompilator Anda sudah memiliki parameter seperti -o something.oAnda mungkin juga ingin mengubahnya menjadi -o something.i. Jika tidak, keluaran yang telah diproses sebelumnya akan ada dalam .ofile.
Tor Klingberg

@TorKlingberg Dapatkah saya melakukan ini untuk beberapa file sekaligus?
pengguna2808264

@ user2808264gcc -E file1.c file2.c ...
Matthieu

68

cpp adalah preprocessor.

Jalankan cpp filename.cuntuk mengeluarkan kode yang telah diproses sebelumnya, atau lebih baik, alihkan ke file dengan cpp filename.c > filename.preprocessed.


2
Saya rasa ini adalah jawaban terbaik karena mendemonstrasikan cpp secara langsung. Sistem Linux (setidaknya Manjaro) tampaknya memiliki -E secara default juga. Saya mendapatkan hasil yang sama dari perintah ini. diffternyata tidak ada perbedaan dalam file. Ini juga terlihat seperti cara yang berguna untuk memproses kode yang mencari kesalahan di makro Anda. Pertanyaan bagus dan jawaban bagus (IALCTHW).
lee8oi

17

Saya menggunakan gcc sebagai preprocessor (untuk file html.) Ia melakukan apa yang Anda inginkan. Ini memperluas arahan "# -", kemudian mengeluarkan file yang dapat dibaca. (TIDAK ADA preprosesor C / HTML lain yang pernah saya coba melakukan ini- mereka menggabungkan baris, mencekik karakter khusus, dll.) Dengan asumsi Anda telah menginstal gcc, baris perintahnya adalah:

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

(Tidak harus 'cpp'.) Ada penjelasan yang sangat bagus tentang penggunaan ini di http://www.cs.tut.fi/~jkorpela/html/cpre.html .

"-Traditional-cpp" mempertahankan spasi & tab.


Terima kasih banyak, ini sangat membantu untuk menghasilkan python cffi cdef!
amirouche

13

-save-temps

Ini adalah opsi bagus lainnya untuk diingat:

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

main.c

#define INC 1

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

dan sekarang, selain keluaran normal main.o, direktori kerja saat ini juga berisi file berikut:

  • main.i adalah file prepossessed yang diinginkan yang berisi:

    # 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 adalah bonus :-) dan berisi rakitan yang dihasilkan:

        .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

Jika Anda ingin melakukannya untuk file dalam jumlah besar, pertimbangkan untuk menggunakan:

 -save-temps=obj

yang menyimpan file perantara ke direktori yang sama dengan -ooutput objek alih-alih direktori kerja saat ini, sehingga menghindari potensi konflik nama dasar.

Keuntungan dari opsi -Eini adalah mudah untuk menambahkannya ke skrip build apa pun, tanpa banyak mengganggu build itu sendiri.

Hal keren lainnya tentang opsi ini adalah jika Anda menambahkan -v:

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

itu benar-benar menunjukkan file eksplisit yang digunakan dan bukan sementara yang jelek di bawah /tmp, jadi mudah untuk mengetahui dengan tepat apa yang sedang terjadi, yang mencakup langkah-langkah preprocessing / kompilasi / perakitan:

/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

Diuji di Ubuntu 19.04 amd64, GCC 8.3.0.


1
Jauh lebih elegan daripada -E karena saya bisa menambahkan -save-temps ke CFLAGS tanpa mengubah perilaku keseluruhan skrip build. Terima kasih!
EvertW

Ini memang sangat berguna, dan -E sangat nyaman untuk file tunggal.
Subin Sebastian


1

Misalkan kita memiliki file sebagai Message.cpp atau file .c

Langkah 1: Preprocessing (Argument -E)

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

File P1 yang dihasilkan memiliki makro yang diperluas dan konten file header dan komentar dihilangkan.

Langkah 2: Terjemahkan file Preprocessed ke assembly (Argument -S). Tugas ini dilakukan oleh compiler

g ++ -S. \ Message.cpp

Assembler (ASM) dibuat (Message.s). Ia memiliki semua kode perakitan.

Langkah 3: Terjemahkan kode assembly ke kode Objek. Catatan: Message.s dibuat di Step2. g ++ -c. \ Message.s

File Objek dengan nama Message.o dibuat. Ini adalah bentuk biner.

Langkah 4: Menautkan file objek. Tugas ini dilakukan oleh linker

g ++. \ Message.o -o MessageApp

File exe MessageApp.exe dibuat di sini.

#include <iostream>
using namespace std;

 //This a sample program
  int main()
{
cout << "Hello" << endl;
 cout << PQR(P,K) ;
getchar();
return 0;
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.