Подтвердить что ты не робот

Может ли gcc вывести код C после предварительной обработки?

Я использую библиотеку с открытым исходным кодом, которая, как представляется, имеет множество предпроцессорных директив для поддержки многих языков, отличных от C. Чтобы я мог изучить, что делает библиотека, мне бы хотелось увидеть код C, который я компиляция после предварительной обработки, больше похожа на то, что я бы написал.

Может ли gcc (или любой другой инструмент, обычно доступный в Linux) читать эту библиотеку, но выводить код C, который имеет предварительную обработку, преобразованную во что угодно и также читается человеком?

4b9b3361

Ответ 1

Да. Передайте gcc -E. Это выведет предварительно обработанный исходный код.

Ответ 2

cpp является препроцессором.

Запустите cpp filename.c, чтобы вывести предварительно обработанный код или, лучше, перенаправить его в файл с помощью cpp filename.c > filename.preprocessed.

Ответ 3

Я использую GCC в качестве препроцессора (для HTML файлов.) Он делает то, что вы хотите. Он раскрывает директивы "# -", а затем выводит читаемый файл. (Ни один из других препроцессоров C/HTML, которые я пытался сделать, this- объединяет строки, задыхается от специальных символов и т.д.) Предполагается, что у вас установлен gcc, командная строка:

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

(Не обязательно должен быть "cpp".) Отличное описание этого использования на http://www.cs.tut.fi/~jkorpela/html/cpre.html.

"-Traditional-cpp" сохраняет пробелы и табуляции.

Ответ 4

Run:

gcc -E <file>.c

или

g++ -E <file>.cpp

Ответ 5

-save-temps

Это еще один хороший вариант, чтобы иметь в виду:

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

main.c

#define INC 1

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

и теперь, кроме обычного вывода main.o, текущий рабочий каталог также содержит следующие файлы:

  • main.i - это нужный файл, содержащий:

    # 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 это бонус :-) и содержит сгенерированную сборку:

        .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
    

Если вы хотите сделать это для большого количества файлов, попробуйте вместо этого:

 -save-temps=obj

который сохраняет промежуточные файлы в том же каталоге, что и -o объекта -o вместо текущего рабочего каталога, что позволяет избежать потенциальных конфликтов -o.

Преимущество этой опции перед -E том, что ее легко добавить в любой скрипт сборки, не сильно влияя на саму сборку.

Еще одна интересная вещь об этой опции, если вы добавите -v:

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

на самом деле он показывает явные файлы, используемые вместо некрасивых временных файлов в /tmp, поэтому легко точно знать, что происходит, включая этапы предварительной обработки/компиляции/сборки:

/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

Протестировано в Ubuntu 19.04 amd64, GCC 8.3.0.

Ответ 6

Предположим, у нас есть файл в виде Message.cpp или .c файл

Этапы 1: предварительная обработка (аргумент -E)

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

Сгенерированный файл P1 содержит расширенные макросы и содержимое заголовочного файла, а комментарии удаляются.

Шаг 2. Переведите предварительно обработанный файл в сборку (аргумент -S). Эта задача выполняется компилятором

g++ -S.\Message.cpp

Ассемблер (ASM) генерируется (Message.s). Он имеет весь код сборки.

Шаг 3: Переведите ассемблерный код в объектный код. Примечание. Message.s был сгенерирован на шаге 2. g++ -c.\Message.s

Создается объектный файл с именем Message.o. Это бинарная форма.

Шаг 4: Связывание объектного файла. Эта задача выполняется компоновщиком

g++.\Message.o -o MessageApp

EXE файл MessageApp.exe создается здесь.

#include <iostream>
using namespace std;

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