预处理后 gcc 可以输出 C 代码吗?

我正在使用一个开源库,它似乎有很多预处理指令来支持 C 以外的许多语言。这样我就可以研究这个库在做什么,我希望看到预处理后编译的 C 代码,更像是我写的代码。

Gcc (或 Linux 中通常可用的任何其他工具)可以读取这个库但输出 C 代码,这些代码已经将预处理转换为任何内容,并且人类也可以读取吗?

137165 次浏览

cpp是预处理器。

运行 cpp filename.c以输出预处理代码,或者更好的方法是将其重定向到具有 cpp filename.c > filename.preprocessed.

是的。传递 gcc -E选项。这将输出预处理的源代码。

我使用 gcc 作为预处理器(用于 html 文件)你想怎样就怎样。它展开“ # ——”指令,然后输出一个可读的文件。(我所尝试的其他 C/HTML 预处理器都没有这样做——它们连接行,阻塞特殊字符,等等)假设您已经安装了 gcc,命令行是:

Gcc-E-x c-P-C-傳統-cpp code _ before. cpp > code _ after. cpp

(不一定非得是‘ cpp’) http://www.cs.tut.fi/~jkorpela/html/cpre.html上对这种用法有很好的描述。

“-傳統-cpp”保留空格和制表符。

跑步:

gcc -E <file>.c

或者

g++ -E <file>.cpp

-save-temps

这是另一个不错的选择:

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

总机

#define INC 1


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

现在,除了正常的输出 ABc0之外,当前的工作目录还包含以下文件:

  • 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对象输出相同的目录,而不是当前工作目录,从而避免潜在的基名冲突。

-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中测试。

制定预定目标

CMake 自动为预处理文件提供一个目标:

make help

告诉我们,我们可以做到:

make main.i

这个目标运行:

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

这样文件可以在 CMakeFiles/main.dir/main.c.i上看到

在 cmake 3.16.1上测试。

假设我们有一个 Message.cpp 或. c 文件

步骤1: 预处理(参数 -E)

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

生成的 P1文件已经扩展了宏和头文件的内容和注释被删除。

步骤2: 将预处理文件翻译成程序集(参数 -S)。这个任务由编译器完成

g++ -S .\Message.cpp

生成一个汇编程序(ASM)(Message.s) ,它包含所有的汇编代码。

步骤3: 将汇编代码翻译成对象代码。

g++ -c .\Message.s

生成一个名为 Message.o 的 Object 文件,它是二进制形式。

步骤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;
}