我使用的是一个开源库,它似乎有很多预处理指令来支持C以外的许多语言。这样我就可以研究库在做什么,我想看看我在预处理后编译的C代码,更像我写的。gcc(或Linux中常用的任何其他工具)是否可以读取这个库,但输出的C代码可以将预处理转换为任何内容,并且也可以被人类读取?
bvjveswy1#
是的。将-E选项传递给gcc。这将输出预处理的源代码。
-E
xtupzzrd2#
cpp是预处理器。运行cpp filename.c以输出预处理后的代码,或者更好的方法是将其重定向到一个包含cpp filename.c > filename.preprocessed的文件。
cpp
cpp filename.c
cpp filename.c > filename.preprocessed
rqdpfwrv3#
-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.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
文档: www.example.com
-save-temps=obj
如果要对大量文件执行此操作,请考虑改用:
它将中间文件保存到与-o对象输出相同的目录,而不是当前工作目录,从而避免潜在的基名冲突。例如:
-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:
-v
gcc -save-temps -c -o main.o -v main.c
它实际上显示了在/tmp下使用的显式文件,而不是丑陋的临时文件,因此很容易确切地知道发生了什么,其中包括预处理/编译/汇编步骤:
/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(迪斯科丁戈)amd 64,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.c.i处看到该文件在cmake 3上测试。16.1.
CMakeFiles/main.dir/main.c.i
hgc7kmma4#
我使用gcc作为一个预处理器(html文件)。)它做的正是你想要的。它展开“#--”指令,然后输出一个可读的文件。(我尝试过的其他C/HTML预处理器中没有一个这样做--它们连接行,阻塞特殊字符等等。)假设你已经安装了gcc,命令行是:gcc -E -x c -P -C -traditional-cpp code_before.cpp〉code_after.人民党(不一定是“cpp”。http://www.cs.tut.fi/~jkorpela/html/cpre.html中有一个关于这种用法的极好描述。“-traditional-cpp”保留空格和制表符。
u2nhd7ah5#
运行:
gcc -E <file>.c
或
g++ -E <file>.cpp
7eumitmz6#
假设我们有一个Message文件。cpp或.c文件
**步骤一:**预处理(参数-E)
g++ -E .\Message.cpp > P1
生成的P1文件已扩展宏,头文件内容和注解已剥离。
**第二步:**将预处理文件转换为程序集(参数-S)。这个任务是由编译器完成的
-S
g++ -S .\Message.cpp
生成汇编程序(ASM)(消息。s)。它有所有的汇编代码。
**第三步:**将汇编代码转换为目标代码。注:消息。s在步骤2中生成。
g++ -c .\Message.s
名为Message的对象文件。o生成。它是二进制形式。
**第四步:**链接目标文件。此任务由链接器完成
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; }
6条答案
按热度按时间bvjveswy1#
是的。将
-E
选项传递给gcc。这将输出预处理的源代码。xtupzzrd2#
cpp
是预处理器。运行
cpp filename.c
以输出预处理后的代码,或者更好的方法是将其重定向到一个包含cpp filename.c > filename.preprocessed
的文件。rqdpfwrv3#
-save-temps
与
-E
相比,此选项的优点是可以轻松地将其添加到任何构建脚本中,而不会对构建本身造成太多干扰:main.c
现在,除了正常的输出
main.o
外,当前工作目录还包含以下文件:main.i
是所需的预先拥有的文件,包含:main.s
是一个额外的:-),并包含生成的程序集:文档: www.example.com
-save-temps=obj
如果要对大量文件执行此操作,请考虑改用:
它将中间文件保存到与
-o
对象输出相同的目录,而不是当前工作目录,从而避免潜在的基名冲突。例如:
导致创建文件:
很明显,苹果计划接管世界。
-save-temps -v
这个选项的另一个很酷的事情是,如果你添加
-v
:它实际上显示了在
/tmp
下使用的显式文件,而不是丑陋的临时文件,因此很容易确切地知道发生了什么,其中包括预处理/编译/汇编步骤:在Ubuntu 19中测试。04(迪斯科丁戈)amd 64,GCC 8.3.0.
CMake预定义目标
CMake自动为预处理文件提供目标:
向我们展示了我们可以做到的:
目标运行:
因此可以在
CMakeFiles/main.dir/main.c.i
处看到该文件在cmake 3上测试。16.1.
hgc7kmma4#
我使用gcc作为一个预处理器(html文件)。)它做的正是你想要的。它展开“#--”指令,然后输出一个可读的文件。(我尝试过的其他C/HTML预处理器中没有一个这样做--它们连接行,阻塞特殊字符等等。)假设你已经安装了gcc,命令行是:
gcc -E -x c -P -C -traditional-cpp code_before.cpp〉code_after.人民党
(不一定是“cpp”。http://www.cs.tut.fi/~jkorpela/html/cpre.html中有一个关于这种用法的极好描述。
“-traditional-cpp”保留空格和制表符。
u2nhd7ah5#
运行:
或
7eumitmz6#
假设我们有一个Message文件。cpp或.c文件
**步骤一:**预处理(参数
-E
)生成的P1文件已扩展宏,头文件内容和注解已剥离。
**第二步:**将预处理文件转换为程序集(参数
-S
)。这个任务是由编译器完成的生成汇编程序(ASM)(消息。s)。它有所有的汇编代码。
**第三步:**将汇编代码转换为目标代码。注:消息。s在步骤2中生成。
名为Message的对象文件。o生成。它是二进制形式。
**第四步:**链接目标文件。此任务由链接器完成
一个exe文件MessageApp。exe在这里生成。