1. 源文件编译后生成什么文件
在C语言中,我们首先需要编写程序源代码,而这些源代码需要被编译成可执行文件才能在计算机中运行。因此,在C语言中编译器会将源代码编译成目标文件和可执行文件。
其中,目标文件是编译器生成的中间文件,包含了源代码被转化后的机器语言代码和数据。而可执行文件则是最终能够在计算机中运行的文件。
在C语言中,源代码通常保存在以“.c”为后缀名的文件中,编译器会将其编译成以“.o”为后缀名的目标文件。而在将所有的目标文件链接起来之后,就可以生成可执行文件了。
1.1 目标文件
目标文件是编译器生成的中间文件,其中包含了源代码被转化后的机器语言代码和数据。它是最终可执行文件的一个必要部分,也是链接器处理的主要对象。
为了更好地理解目标文件,让我们来看一个简单的例子:
#include <stdio.h>
int main()
{
printf("Hello World!\n");
return 0;
}
将上述代码保存为“hello.c”,并使用C编译器编译后,可以在同一目录下看到一个名为“hello.o”的目标文件。然后使用“objdump”命令可以查看目标文件中包含的机器指令。
$ objdump -d hello.o
输出的结果可能很长,但其中一部分是这样的:
$ objdump -d hello.o
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 10 sub $0x10,%rsp
8: c7 45 fc 48 65 6c 6c movl $0x6c6c6548,-0x4(%rbp)
f: c7 45 f8 6f 20 57 6f movl $0x6f57206f,-0x8(%rbp)
16: c7 45 f4 72 6c 64 21 movl $0x21646c72,-0xc(%rbp)
1d: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi
24: b0 00 mov $0x0,%al
26: e8 00 00 00 00 callq 2b <main+0x2b>
2b: b8 00 00 00 00 mov $0x0,%eax
30: c9 leaveq
31: c3 retq
可以看到,目标文件中包含了编译器将源代码转换成的机器指令,以及对应的地址信息。当链接器将多个目标文件链接起来时,这些地址信息会被重新排列,以便于最终生成可执行文件。
1.2 可执行文件
可执行文件是可以被计算机直接执行的文件,是源代码编译和链接的最终产物。在C语言中,可执行文件通常以“.out”或“.exe”为后缀名。
回到之前的例子,使用C编译器将源代码编译成可执行文件的命令为:
$ gcc hello.c -o hello.out
编译完成后,可以在同一目录下看到名为“hello.out”的可执行文件。直接运行该文件即可在终端中输出“Hello World!”。
$ ./hello.out
Hello World!
2. 源文件编译的过程
源文件编译过程包括预处理、编译、汇编和链接四个步骤。
2.1 预处理
预处理指的是在编译前对源代码进行预处理,包括识别以“#”开头的特殊指令,如#include和#define关键字。同时,预处理也会对宏进行替换、注释删除、条件编译等操作。最终生成预处理后的源文件。
对于之前的“hello.c”代码,使用预处理命令可以查看经过预处理后的源文件内容:
$ gcc -E hello.c
可以看到,预处理后的代码中包含了包括头文件“stdio.h”中的内容:
# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "hello.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
...
2.2 编译
编译是将预处理后的源文件转换成汇编代码的过程。在编译过程中,编译器会检查代码语法错误,并将代码转化成汇编语言形式。
同样以“hello.c”为例,可以将其编译成汇编代码:
$ gcc -S hello.c
可以看到生成了一个名为“hello.s”的汇编代码文件。
2.3 汇编
汇编是将编译生成的汇编代码转换成机器代码的过程。在汇编过程中,汇编器将汇编代码转换成二进制指令,并生成目标文件,其中包含机器指令、元素大小、符号表等。
对于“hello.s”代码文件,可以使用汇编命令将其转换成目标文件:
$ gcc -c hello.s
在同一目录下可以看到生成了名为“hello.o”的目标文件。
2.4 链接
链接是将各个目标文件(可以是C源代码文件编译得到的多个目标文件,也可以是编译目标文件的库)进行链接,生成最终的可执行文件的过程。
在对目标文件进行链接时,链接器会将各个目标文件中的符号解析,找到符号对应的定义,并调整地址信息等。最终生成可执行文件。
同样以之前的例子为例,可以将“hello.o”文件和其他需要的库文件进行链接,生成可执行文件:
$ gcc -o hello.out hello.o
在同一目录下可以看到生成了名为“hello.out”的可执行文件。
3. 总结
在C语言中,源文件编译过程一般包括预处理、编译、汇编和链接四个步骤。其中,在编译过程中,源文件会被编译器编译成目标文件和可执行文件。目标文件是编译器生成的中间文件,包含了源代码被转化后的机器语言代码和数据;可执行文件则是最终能够在计算机中运行的文件。在编译过程中,每个步骤都将源代码转换成不同的形式,最终生成的可执行文件包含了整个源代码的机器指令和数据。
了解源文件编译过程对于理解C语言程序的工作原理和优化程序有重要意义。希望本文对您了解源文件编译后生成的文件有所帮助。