我们在哪里使用.i文件以及如何生成它们?

Nih*_*ish 7 c file-extension gcc

我正在浏览GCC手册页,我找到了以下行:

 file.i
           C source code that should not be preprocessed.
Run Code Online (Sandbox Code Playgroud)

我知道运行gcc -E foo.c在预处理后会停止编译器; 但是创建.i文件的真实世界应用是什么.

还有一种方法可以生成.i除以外的文件gcc foo.c -E > foo.i吗?

Sat*_*ish 8

这些.i文件也称为"纯C文件".在预处理阶段

  1. 将包含头文件.

  2. 宏将被替换.

  3. 评论已删除.

  4. 用于条件编译.如果你查看.i文件,你可以看到这些东西.

生成.i文件的命令是 -

gcc -E foo.c -o foo.i
Run Code Online (Sandbox Code Playgroud)


Gab*_*les 7

一个file.i文件是:

不应预处理的 C 源代码。

来源man gcc然后搜索“ \.i”。
详细步骤man gcc,然后按/键搜索,然后输入\.i,然后按Enter键,然后n反复按键,直到找到为止。

这意味着.i文件是经过预处理的源代码,因此它已经包含:

  1. 包含所有头文件
  2. 宏被替换
  3. 并删除了评论

...正如@Sathish在他的回答中所说。您还会注意到 gcc 添加了大量现在以#字符开头的特殊“注释” ,例如:

# 1 "main.c"  
# 1 "<built-in>"  
# 1 "<command-line>"  
# 1 "/usr/include/stdc-predef.h" 1 3 4  
# 1 "<command-line>" 2  
# 1 "main.c"  
# 44 "main.c"  
# 1 "/usr/include/stdio.h" 1 3 4  
# 27 "/usr/include/stdio.h" 3 4  
# 1 "/usr/include/features.h" 1 3 4  
# 374 "/usr/include/features.h" 3 4  
# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4  
Run Code Online (Sandbox Code Playgroud)

请注意,像这样的简单程序:

#include <stdio.h>

int main()
{
    printf("hello world\n");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

用这个编译:

gcc -Wall -std=c99 -O0 -save-temps=obj main.c -o ./bin/main
Run Code Online (Sandbox Code Playgroud)

将生成一个main.i大约 682 行长的文件,main()上面显示的函数就在最后。

如何生成所有中间文件,包括.i文件:

我的偏好是在项目的本地文件夹中一次性生成所有中间文件(.i, .o, .s,而不仅仅是.i使用的文件-E),bin如下所示:

mkdir bin
gcc -save-temps=obj foo.c -o ./bin/foo
Run Code Online (Sandbox Code Playgroud)

现在您在“foo/bin”目录中有以下内容:

foo     # compiled binary program (AKA: combined "object file", 
        # "executable", "binary", "program", or "machine code")
foo.i   # intermediate, preprocessed C file  
foo.o   # individual object file  
foo.s   # assembly file
Run Code Online (Sandbox Code Playgroud)

运行程序当然是:

./bin/foo
Run Code Online (Sandbox Code Playgroud)

关于“目标文件”和“可执行文件”的说明

请注意,最终输出的foo可执行文件被称为“编译的二进制程序”、“程序”、(组合的)“目标文件”、“可执行文件”、“二进制文件”,或者只是“机器代码”,或者“一个和零”(10101010)。这是一个目标文件的目标文件格式,因为是个人“*的.o”的目标文件被合并成一个由连接器来创建它。链接器将所有“*.o”目标文件合并为一个,以生成最终的foo可执行文件或合并的目标文件

GNU 链接器 ( ld) 手册说明如下。请参阅“3.1 基本链接脚本概念”部分:https : //sourceware.org/binutils/docs/ld/Basic-Script-Concepts.html#Basic-Script-Concepts(已添加重点,以及方括号中的内容[]):

3.1 基本链接描述文件概念

我们需要定义一些基本概念和词汇来描述链接描述文件语言。

链接器将输入文件 [单独的 *.o 目标文件] 合并到一个输出文件中。输出文件和每个输入文件都采用称为目标文件格式的特殊数据格式。每个文件称为一个目标文件。输出文件通常称为可执行文件,但出于我们的目的,我们也将其称为目标文件。每个目标文件都有一个部分列表。我们有时将输入文件中的部分称为输入部分;类似地,输出文件中的一个是一个输出节

欲了解更多信息。关于目标文件,您还可以在这里看到我的其他两个答案:

  1. 如何在编译时找出 STM32 的 Flash 存储器和动态存储器 (SRAM) 已用完多少?
  2. 将 binutils `size` 输出从“sysv”格式(`size --format=sysv my_executable`)转换为“berkeley”格式(`size --format=berkeley my_executable`)