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

发布于 2024-10-16 05:02:27 字数 159 浏览 8 评论 0原文

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

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

I'm using an open source library which seems to have lots of preprocessing directives to support many languages other than C. So that I can study what the library is doing I'd like to see the C code that I'm compiling after preprocessing, more like what I'd write.

Can gcc (or any other tool commonly available in Linux) read this library but output C code that has the preprocessing converted to whatever and is also readable by a human?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

一枫情书 2024-10-23 05:02:27

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

Yes. Pass gcc the -E option. This will output preprocessed source code.

柠栀 2024-10-23 05:02:27

cpp 是预处理器。

运行 cpp filename.c 输出预处理后的代码,或者更好的是,将其重定向到一个文件
cpp 文件名.c >文件名.预处理

cpp is the preprocessor.

Run cpp filename.c to output the preprocessed code, or better, redirect it to a file with
cpp filename.c > filename.preprocessed.

风向决定发型 2024-10-23 05:02:27

-save-temps

-E 相比,此选项的优点是可以轻松地将其添加到任何构建脚本中,而不会过多干扰构建本身:

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“<内置>”
    # 1 “<命令行>”
    # 31 “<命令行>”
    # 1 “/usr/include/stdc-predef.h” 1 3 4
    # 32 “<命令行>” 2
    # 1 “main.c”

    int myfunc(int i) {
    返回 i + 1;
    }

  • main.s 是一个额外的好处:-)并包含生成的程序集:

    <前><代码> .文件“main.c”
    。文本
    .globl myfunc
    .type myfunc,@function
    我的函数:
    .LFB0:
    .cfi_startproc
    推q%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
    添加$1,%eax
    弹出%rbp
    .cfi_def_cfa 7, 8
    雷特
    .cfi_endproc
    .LFE0:
    .size myfunc, .-myfunc
    .ident“GCC:(Ubuntu 8.3.0-6ubuntu1)8.3.0”
    .section .note.GNU-stack,"",@progbits

文档:https://gcc.gnu.org/onlinedocs/gcc/Developer-Options.html#index-save-temps

-save-temps =obj

如果您想对大量文件执行此操作,请考虑使用:

-save-temps=obj

它将中间文件保存到与 -o 对象输出相同的目录中当前工作目录的名称,从而避免潜在的基本名称冲突。

例如:

gcc -save-temps -c -o out/subdir/main.o subdir/main.c

导致文件的创建:

out/subdir/main.i
out/subdir/main.o
out/subdir/main.s

显然,苹果计划接管世界。

-save-temps -v

关于此选项的另一个很酷的事情是,如果您添加 -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 (Disco Dingo) amd64、GCC 8.3.0 中测试。

CMake 预定义目标

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 中看到该文件。 ci

在 cmake 3.16.1 上测试。

-save-temps

The advantage of this option over -E is that it is easy to add it to any build script, without interfering much in the build itself:

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

main.c

#define INC 1

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

and now, besides the normal output main.o, the current working directory also contains the following files:

  • main.i is the desired prepossessed file containing:

    # 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 is a bonus :-) and contains the generated 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
    

Docs: https://gcc.gnu.org/onlinedocs/gcc/Developer-Options.html#index-save-temps

-save-temps=obj

If you want to do it for a large number of files, consider using instead:

-save-temps=obj

which saves the intermediate files to the same directory as the -o object output instead of the current working directory, thus avoiding potential basename conflicts.

For example:

gcc -save-temps -c -o out/subdir/main.o subdir/main.c

leads to the creation of files:

out/subdir/main.i
out/subdir/main.o
out/subdir/main.s

Clearly an Apple plot to take over the world.

-save-temps -v

Another cool thing about this option is if you add -v:

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

it actually shows the explicit files being used instead of ugly temporaries under /tmp, so it is easy to know exactly what is going on, which includes the preprocessing / compilation / assembly steps:

/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

Tested in Ubuntu 19.04 (Disco Dingo) amd64, GCC 8.3.0.

CMake predefined targets

CMake automatically provides a targets for the preprocessed file:

make help

shows us that we can do:

make main.i

and that target runs:

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 the file can be seen at CMakeFiles/main.dir/main.c.i

Tested on cmake 3.16.1.

年少掌心 2024-10-23 05:02:27

我使用 gcc 作为预处理器(用于 html 文件)。它正是您想要的。它扩展“#--”指令,然后输出一个可读文件。 (我尝试过的其他 C/HTML 预处理器都没有这样做 - 它们连接行,阻塞特殊字符等。)假设您安装了 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”保留空格和空格。选项卡。

I'm using gcc as a preprocessor (for html files.) It does just what you want. It expands "#--" directives, then outputs a readable file. (NONE of the other C/HTML preprocessors I've tried do this- they concatenate lines, choke on special characters, etc.) Asuming you have gcc installed, the command line is:

gcc -E -x c -P -C -traditional-cpp code_before.cpp > code_after.cpp

(Doesn't have to be 'cpp'.) There's an excellent description of this usage at http://www.cs.tut.fi/~jkorpela/html/cpre.html.

The "-traditional-cpp" preserves whitespace & tabs.

不醒的梦 2024-10-23 05:02:27

运行:

gcc -E <file>.c

g++ -E <file>.cpp

Run:

gcc -E <file>.c

or

g++ -E <file>.cpp
万劫不复 2024-10-23 05:02:27

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

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

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

生成的 P1 文件已扩展宏,头文件内容和注释为脱光了。

第 2 步: 将预处理文件转换为程序集(参数 -S)。这个任务是由编译器完成的,

g++ -S .\Message.cpp

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

第 3 步:将汇编代码转换为对象代码。注意:Message.s是在Step2中生成的。

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

Suppose we have a file as Message.cpp or a .c file

Steps 1: Preprocessing (Argument -E)

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

P1 file generated has expanded macros and header file contents and comments are stripped off.

Step 2: Translate Preprocessed file to assembly (Argument -S). This task is done by compiler

g++ -S .\Message.cpp

An assembler (ASM) is generated (Message.s). It has all the assembly code.

Step 3: Translate assembly code to Object code. Note: Message.s was generated in Step2.

g++ -c .\Message.s

An Object file with the name Message.o is generated. It is the binary form.

Step 4: Linking the object file. This task is done by linker

g++ .\Message.o -o MessageApp

An exe file MessageApp.exe is generated here.

#include <iostream>
using namespace std;

//This a sample program
int main()
{
  cout << "Hello" << endl;
  cout << PQR(P,K) ;
  getchar();
  return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文