如何查看C预处理器输出?

问题描述 投票:0回答:7

在转换为目标文件之前,如何查看 C 预处理器生成的输出?

我想看看宏定义对我的代码做了什么。

gcc macros c-preprocessor
7个回答
127
投票
gcc -E file.c

g++ -E file.cpp

将为您做这件事。 -E 开关强制编译器在预处理阶段后停止,将当前所有内容吐出到标准输出。

注意:当然你必须有一些#include 指令。包含的文件也经过预处理,因此您可能会获得大量输出。

对于 Visual C++,开关是 /E,它将预处理器输出吐到屏幕上。


25
投票

您也可以直接调用C预处理器。

cpp infile outfile

查看

man cpp
了解更多信息。


13
投票

对于海湾合作委员会,

gcc -E -dM file.c

g++ -E -dM file.cpp

应该完成这项工作。 -dM,正如 GNU 预处理器手册所说的那样,应该为预处理器执行期间定义的所有宏(包括预定义的宏)生成一个“#define”指令列表。


7
投票
这取决于您使用的编译器。

使用 GCC,您可以在命令行上指定
-E

 标志,让编译器生成预处理器输出。


5
投票

-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 "<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


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

-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 22.10 amd64、GCC 8.3.0 中测试。

Visual Studio 代码

悬停宏会自动展开它们,它往往工作得很好!不确定是否需要正确的跨文件引用,因为我通常使用 clangd:

VSCode“转到定义”不起作用


4
投票
如果使用 Jetbrains 的 CLion,您可以使用“clangd:预处理当前 TU”操作

所以点击

shift

 
shift
 并开始输入 clangd...

最好将其分配给快捷方式,以便在首选项->键盘映射中更简单地重用:

大声喊出

marcosbento

PS:TU的意思是“翻译单元”(参见这里

LLVM翻译单元


2
投票
您可以查看此处描述的我的脚本:

http://mosermichael.github.io/cstuff/all/projects/2011/09/16/preprocessor.html

它将预处理器输出格式化为(希望)可读的 html 文档:由于预处理器而不同的行会在文件中标记。

© www.soinside.com 2019 - 2024. All rights reserved.