如何查看C预处理器生成的输出,在转换为目标文件之前?我想看看宏定义对我的代码做了什么。
tag5nh1u1#
gcc -E file.c
或
g++ -E file.cpp
会为你做这些-E开关强制编译器在预处理阶段结束后停止,将当前所有内容输出到标准输出。注意:你肯定有一些#include指令。包含的文件也会被预处理,因此您可能会得到大量的输出。对于Visual C++,开关是/E,它将预处理器输出分配到屏幕。
xghobddn2#
也可以直接调用C预处理器。
cpp infile outfile
查看man cpp了解更多信息。
man cpp
wbrvyc0a3#
对于GCC,
gcc -E -dM file.c
g++ -E -dM file.cpp
应该能胜任-dM,正如GNU预处理器手册所说,应该为预处理器执行期间定义的所有宏生成一个'#define'指令列表,包括预定义的宏。
jexiocij4#
这取决于您使用的编译器。使用GCC,您可以在命令行上指定-E标志,让编译器生成预处理器输出。
-E
js4nwp545#
如果使用Jetbrains的CLion,您可以使用操作“clangd:预处理当前TU”所以点击shiftshift并开始输入clangd。..
shift
最好将其分配给一个快捷方式,以便在首选项-〉keymap中更简单地重用:
向marcosbento大喊PS:TU的意思是“翻译单元”(参见此处LLVM translation unit)
jjhzyzn06#
你可以看看我在这里描述的脚本:http://mosermichael.github.io/cstuff/all/projects/2011/09/16/preprocessor.html它将预处理器输出格式化为(希望)可读的html文档:在文件中标记由于预处理器而不同的行。
bf1o4zei7#
-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
-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 22中测试。10 amd64,GCC 8。3.0.
7条答案
按热度按时间tag5nh1u1#
或
会为你做这些-E开关强制编译器在预处理阶段结束后停止,将当前所有内容输出到标准输出。
注意:你肯定有一些#include指令。包含的文件也会被预处理,因此您可能会得到大量的输出。
对于Visual C++,开关是/E,它将预处理器输出分配到屏幕。
xghobddn2#
也可以直接调用C预处理器。
查看
man cpp
了解更多信息。wbrvyc0a3#
对于GCC,
或
应该能胜任-dM,正如GNU预处理器手册所说,应该为预处理器执行期间定义的所有宏生成一个'#define'指令列表,包括预定义的宏。
jexiocij4#
这取决于您使用的编译器。
使用GCC,您可以在命令行上指定
-E
标志,让编译器生成预处理器输出。js4nwp545#
如果使用Jetbrains的CLion,您可以使用操作“clangd:预处理当前TU”
所以点击
shift
shift
并开始输入clangd。..最好将其分配给一个快捷方式,以便在首选项-〉keymap中更简单地重用:
向marcosbento大喊
PS:TU的意思是“翻译单元”(参见此处LLVM translation unit)
jjhzyzn06#
你可以看看我在这里描述的脚本:
http://mosermichael.github.io/cstuff/all/projects/2011/09/16/preprocessor.html
它将预处理器输出格式化为(希望)可读的html文档:在文件中标记由于预处理器而不同的行。
bf1o4zei7#
-save-temps
与
-E
相比,此选项的最大优点是可以很容易地将其添加到任何构建脚本中,而不会对构建本身造成太多干扰:main.c
现在,除了正常的输出
main.o
外,当前工作目录还包含以下文件:main.i
是一个包含所需的预处理文件:main.s
是一个奖励,包含所需的生成程序集:-save-temps=obj
如果要对大量文件执行此操作,请考虑改用:
它将中间文件保存到与
-o
对象输出相同的目录,而不是当前工作目录,从而避免潜在的基名冲突。例如:
导致创建文件:
很明显,苹果计划接管世界。
-save-temps -v
这个选项的另一个很酷的事情是,如果你添加
-v
:它实际上显示了在
/tmp
下使用的显式文件,而不是丑陋的临时文件,因此很容易确切地知道发生了什么,其中包括预处理/编译/汇编步骤:在Ubuntu 22中测试。10 amd64,GCC 8。3.0.