预处理.i,编译器输出.s,汇编器输出.o
预处理器输出 (.i 文件)
预处理器接受原始的 C 源代码(.c 文件)并进行预处理,这包括处理 #include
指令,替换宏定义 (#define
),处理条件编译 (#if
,#ifdef
,#ifndef
等)。预处理器的输出是 .i
文件,它是经过预处理后的 C 代码,其中所有的宏和 #include
指令都被替换为其具体的内容。.i
文件可以作为编译器的输入。
编译器输出 (.s 文件)
编译器将预处理器输出的 .i
文件作为输入,并将其转换为汇编语言代码。这个过程包括了很多步骤,例如词法分析Lexical,语法分析Parsing,生成抽象语法树AST,优化,以及生成汇编语言代码。编译器输出的是 .s
文件,也就是汇编语言代码。.s
文件可以作为汇编器的输入。
汇编器输出 (.o 文件)
汇编器将编译器输出的 .s
文件作为输入,并将其转换为二进制的目标代码。汇编器的输出是 .o
文件,也就是目标文件。这些目标文件可以作为链接器的输入,链接器将多个 .o
文件链接为一个可执行文件或库文件。
关于重命名和重新编译.i
.i
文件可以重命名为 .c
文件并重新编译。.i
文件本身就是 C 语言代码,只不过它已经进行了预处理,所以可以直接作为编译器的输入。将 .i
文件重命名为 .c
文件并重新编译的情况并不常见,但在某些情况下可能会有用,例如在调试预处理器问题,或者在需要将预处理结果作为源代码的情况下。
重命名 .i
文件为 .c
文件并重新编译的好处是,你可以直接看到预处理的结果,这在调试宏扩展等问题时非常有用。然而,你需要注意,由于 .i
文件已经经过预处理,因此它可能非常大,并且包含大量的代码,这可能会使得代码阅读和理解更加困难。
gcc -save-temps
: 这个命令在 GCC 中有特殊的用途。当你在编译源代码时,GCC 会通过几个阶段,包括预处理、编译、汇编和链接。每个阶段都会生成中间文件。使用-save-temps
选项会让 GCC 在每个阶段之后都保存中间文件,而不是像默认情况那样在整个编译过程结束后删除它们。保存的文件包括预处理器输出(.i文件)
编译器输出(.s文件)
汇编器输出(.o文件)。
gcc -E
: 这个命令用于运行 GCC 的预处理阶段,并将预处理后的源代码输出到标准输出(默认情况下)或指定的文件。预处理阶段包括将所有的宏扩展、处理所有的预处理指令(如 #include、#define 等),同时也会处理条件编译指令(如 #if、#ifdef、#else 等)。这个命令可以让你看到预处理阶段后的代码是如何的,特别是对于调试宏扩展的问题特别有用。