Gcc có thể xuất mã C sau khi xử lý trước không?


104

Tôi đang sử dụng một thư viện mã nguồn mở có vẻ như có rất nhiều lệnh tiền xử lý để hỗ trợ nhiều ngôn ngữ khác ngoài C. Vì vậy, tôi có thể nghiên cứu thư viện đang làm gì, tôi muốn xem mã C mà tôi đang biên dịch sau khi xử lý trước , giống như những gì tôi muốn viết.

Liệu gcc (hoặc bất kỳ công cụ nào khác thường có sẵn trong Linux) có thể đọc thư viện này nhưng xuất ra mã C đã được chuyển đổi tiền xử lý thành bất kỳ thứ gì và con người cũng có thể đọc được không?


Mã preprocessed wont có bất kỳ chỉ thị tiền xử lý nữa nhưng tôi khá chắc chắn nó sẽ được nhiều ít có thể đọc được hơn trước khi được xử lý trước ...
Alex W

2
@AlexW - Điều đó hoàn toàn phụ thuộc vào mức độ khủng khiếp của những người viết mã đã lạm dụng bộ tiền xử lý.
Tên giả vào

1
Vui lòng xem xét thay đổi câu trả lời được chấp nhận của bạn ở đây. gcc -Ehữu ích hơn là phải viết lại dòng để làm cho nó hoạt động cpp.
Màu xám,

Câu trả lời:


193

Đúng. Vượt qua gcc -Etùy chọn. Điều này sẽ xuất ra mã nguồn được xử lý trước.


12
Nếu các lệnh trình biên dịch của bạn đã có một tham số như vậy, -o something.obạn cũng có thể muốn thay đổi nó thành -o something.i. Nếu không, đầu ra được xử lý trước sẽ nằm trong .otệp.
Tor Klingberg

@TorKlingberg Tôi có thể thực hiện việc này cho nhiều tệp cùng một lúc không?
user2808264 18/09/16

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

68

cpp là bộ tiền xử lý.

Chạy cpp filename.cđể xuất mã được xử lý trước hoặc tốt hơn, chuyển hướng nó đến một tệp có cpp filename.c > filename.preprocessed.


2
Tôi nghĩ đây là câu trả lời tốt nhất vì nó thể hiện cpp trực tiếp. Các hệ thống Linux (ít nhất là Manjaro) dường như cũng có -E theo mặc định. Tôi nhận được kết quả tương tự từ lệnh này theo cách nào đó. diffkhông có sự khác biệt trong các tệp. Đây cũng giống như một cách hữu ích để xử lý trước mã tìm kiếm lỗi trong macro của bạn. Câu hỏi hay và một câu trả lời tuyệt vời (IALCTHW).
lee8oi

17

Tôi đang sử dụng gcc làm bộ tiền xử lý (cho các tệp html.) Nó chỉ làm những gì bạn muốn. Nó mở rộng các chỉ thị "# -", sau đó xuất ra một tệp có thể đọc được. (KHÔNG CÓ các bộ tiền xử lý C / HTML khác mà tôi đã thử làm điều này - chúng nối các dòng, ngắt các ký tự đặc biệt, v.v.) Giả sử bạn đã cài đặt gcc, dòng lệnh là:

gcc -E -xc -P -C -traditional-cpp code_before.cpp> code_ after.cpp

(Không nhất thiết phải là 'cpp'.) Có một mô tả tuyệt vời về cách sử dụng này tại http://www.cs.tut.fi/~jkorpela/html/cpre.html .

"-Traditional-cpp" giữ nguyên khoảng trắng & các tab.


Rất cảm ơn, điều này rất hữu ích để tạo cdef python cffi!
amirouche

13

-save-temps

Đây là một lựa chọn tốt khác cần lưu ý:

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

C chính

#define INC 1

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

và bây giờ, ngoài đầu ra bình thường main.o, thư mục làm việc hiện tại còn chứa các tệp sau:

  • main.i là tệp được đánh giá trước mong muốn có chứa:

    # 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 là một phần thưởng :-) và chứa assembly đã tạo:

        .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
    

Nếu bạn muốn làm điều đó cho một số lượng lớn tệp, hãy xem xét sử dụng thay thế:

 -save-temps=obj

trong đó lưu các tệp trung gian vào cùng thư mục với -ođầu ra đối tượng thay vì thư mục làm việc hiện tại, do đó tránh được xung đột tên cơ sở tiềm ẩn.

Ưu điểm của tùy chọn -Enày là có thể dễ dàng thêm nó vào bất kỳ tập lệnh xây dựng nào mà không can thiệp nhiều vào chính quá trình xây dựng.

Một điều thú vị khác về tùy chọn này là nếu bạn thêm -v:

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

nó thực sự hiển thị các tệp rõ ràng đang được sử dụng thay vì các tệp tạm thời xấu xí /tmp, do đó, rất dễ dàng để biết chính xác điều gì đang xảy ra, bao gồm các bước tiền xử lý / biên dịch / lắp ráp:

/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

Đã thử nghiệm trong Ubuntu 19.04 amd64, GCC 8.3.0.


1
Thanh lịch hơn nhiều so với -E vì tôi chỉ có thể thêm -save-temps vào CFLAGS mà không thay đổi hành vi tổng thể của tập lệnh xây dựng. Cảm ơn bạn!
EvertW

Điều này thực sự rất hữu ích và -E rất thuận tiện cho các tệp đơn lẻ.
Subin Sebastian


1

Giả sử chúng ta có một tệp là Message.cpp hoặc tệp .c

Bước 1: Tiền xử lý (Đối số -E)

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

Tệp P1 được tạo đã mở rộng macro và nội dung tệp tiêu đề và nhận xét bị loại bỏ.

Bước 2: Dịch tập tin được xử lý trước sang hợp ngữ (Đối số -S). Tác vụ này được thực hiện bởi trình biên dịch

g ++ -S. \ Message.cpp

Một trình hợp dịch (ASM) được tạo ra (Message.s). Nó có tất cả các mã lắp ráp.

Bước 3: Dịch mã lắp ráp sang mã Đối tượng. Lưu ý: Message.s đã được tạo ở Bước 2. g ++ -c. \ Message.s

Tệp đối tượng có tên Message.o được tạo. Nó là dạng nhị phân.

Bước 4: Liên kết tệp đối tượng. Tác vụ này được thực hiện bởi trình liên kết

g ++. \ Message.o -o MessageApp

Một tệp exe MessageApp.exe được tạo ở đây.

#include <iostream>
using namespace std;

 //This a sample program
  int main()
{
cout << "Hello" << endl;
 cout << PQR(P,K) ;
getchar();
return 0;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.