GCC编译过程
GCC 编译过程分为四个主要步骤,每个步骤都有其特定的任务和输出:
-
预处理:处理宏定义、文件包含和条件编译,生成扩展的源代码文件。
-
编译:将扩展的源代码编译成汇编代码。
-
汇编:将汇编代码转换为目标文件(机器码)。
-
链接:将目标文件和库文件链接成最终的可执行文件。
以下是每个步骤的详细说明:
1. 预处理(Preprocessing)
-
命令:
gcc -E test.c -o test.i
-
解释:
-
预处理是编译过程的第一步,主要将不能编译的头文件、宏定义、注释等内容处理掉,由预处理器
cpp
完成,主要任务包括:-
宏替换:处理
#define
定义的宏,它在预处理阶段进行文本替换。 -
文件包含:处理
#include
指令,它在预处理阶段将头文件的内容插入到当前文件中。。 -
条件编译:处理
#ifdef、#ifndef、#if、#else、#elif 和 #endif
等条件编译指令,根据条件决定是否编译特定的代码段。 -
C语言中
#
开头表示预处理指令,不是语句,不能编译不能执行,只在预处理阶段处理这些指令。预处理指令通常用于宏定义、文件包含、条件编译等。
-
-
预处理的输出是扩展的源代码文件
test.i
,其中已经包含了所有的宏替换和头文件内容。
-
-
输出:预处理结果
test.i
,包含了实际内容替换和文件包含。
2. 编译(Compilation)
-
命令:
gcc -S test.i -o test.s
-
解释:
-
编译是将预处理后的源代码转换为汇编代码的过程,由 GCC 编译器本身完成。
-
编译器解析
test.i
文件中的高级语言代码,生成对应的汇编代码test.s
。 -
该过程包括词法分析、语法分析、语义分析和优化。
-
-
输出:汇编代码文件
test.s
,表示源代码的低级表示。这里编译出来为x86架构的汇编语言,看不懂
3. 汇编(Assembly)
-
命令:
gcc -c test.s -o test.o
-
解释:
-
汇编是将汇编代码转换为机器码(目标文件)的过程,由汇编器
gas
(GNU Assembler)完成。 -
汇编器将
test.s
文件中的汇编指令转换为机器码,生成二进制目标文件test.o
。
-
-
输出:目标文件
test.o
,包含了机器码。由于 vi 只是文本编辑器,只能看到文本,对于二进制文件只能显示乱码。
4. 链接(Linking)
-
命令:
gcc test.o -o test
-
解释:
-
链接是将一个或多个目标文件和库文件链接成可执行文件的过程。
-
由链接器
ld
完成。 -
链接器将目标文件
test.o
与所需的库文件(如 C 标准库)链接起来,解决所有符号引用,生成最终的可执行文件test
。
-
-
输出:最终的可执行文件
test
,可以在目标平台上运行。链接器将多个目标文件和库文件链接成最终的可执行文件:例如,下图中,链接过程中,
extern int a;
告诉编译器a
在另一个目标文件v.o
中定义。链接器会找到v.o
中a
的定义,将其链接到最终的可执行文件中。