C语言编译链接过程

本文详细介绍了C语言在Linux环境下使用GCC编译执行HelloWorld程序的四个步骤:预处理、编译、汇编和链接。预处理阶段处理宏定义、条件编译和头文件;编译阶段进行词法、语法和语义分析;汇编阶段将汇编代码转换为机器指令;链接阶段解决模块间依赖,生成可执行文件。通过理解这一过程,有助于深入学习编程和调试技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C语言编译链接过程

在Linux下,当我们使用GCC来编译Hello World程序时,只需要使用最简单的命令(假设源代码文件名为hello.c);
$gcc hello.c
$./a.out

Hello World

其过程可以分解为4个步骤:
预处理(Prepressing)
编译(Compilation)
汇编(Assembly)
链接(Linking)

在这里插入图片描述
一,预编译
首先是源代码文件hello.c和相关的头文件,如stdio.h等被预编译器cpp预编译成一个.i文件。
第一步预编译的过程相当于如下命令(-E表示只进行预编译):
$gcc -E hello.c -o hello.i
预编译过程主要处理那些源代码文件中的一“#”开始的预编译指令,比如“#include”,“#define”等,
规则:

  1. 将所有的“#define”删除,并且展开所有的宏定义。
  2. 处理所有条件预编译指令,比如“#if”,"#ifdef","#elif","#else","#endif".
  3. 处理“#include”预编译指令,将被包含的文件插入到该编译指令的位置。注意,这个过程是递归进行的,也就是说被包含的文件可能还包含其他文件。
  4. 删除所有的注释“//”和“/* */”.
  5. 添加行号和文件名标识,比如#2“hello.c”2,以便于编译时编译器产生调试用的行号信息及用于编译时产生编译错误或警告时能够显示行号。
  6. 保留所有的#pragma编译器指令,因为编译器需要使用它们
    经过编译后的.i文件不包含任何宏定义,因为所有的宏已经被展开,并且包含的文件也已经被插入到.i文件中。所以当我们无法判断宏定义是否正确或头文件包含是否正确时,可以查看预编译后的文件来确定问题。

二、编译

编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后生产相应的汇编码文件,

词法分析:源代码程序被输入到扫描器,它将源代码分割成一系列记号((Token)包含关键字、标识符、字面量和特殊符号),将标识符放到符号表,将数字、字符串放到文字表。
语法分析:分析表达式是否遵循语法规则。
语义分析:判断语句是否真正有意义。

这个过程往往是我们所说的整个程序构建的核心部分,也是最复杂的部分之一,相当于如下命令:
$gcc -S hello.i -o hello.s
现在版本的GCC把预编译和编译两个步骤合并成一个步骤,使用一个叫ccl的程序来完成它,直接调用完成(如图):
在这里插入图片描述

或者使用如下命令:
$gcc -S hello.c -o hello.s
都可以得到汇编输出文件hello.s。对于C语言的代码来说,这个预编译和编译的程序是ccl,

三、汇编
汇编器是将汇编代码转变成机器可以执行的指令,每一个汇编语言几乎都对应一条机器指令。所以汇编器的汇编过程相当于编译器来讲比较简单,它没有复杂的语法,也没有语义,也不需要做指令优化,只是根据汇编指令和机器指令的对照表一一翻译就可以了,上面的汇编过程我们可以调用该汇编器as来完成:
$as hello.s -o hello.o

或者
$gcc -c hello.s -o hello.o
或者

使用gcc命令从C源代码文件开始,经过预编译、编译和汇编直接输出目标文件(Object File):
$gcc -c hello.c -o hello.o

四、链接
程序分为多个模块后,模块的拼接过程就是链接,链接的主要内容就是把哥哥模块之间相互引用的部分都处理好,使得各个模块之间能够正确的衔接,
静态链接
链接过程:地址和空间分配(Address and Storage Allocation)、符号决议(Symbol Resolution)和重定位(Relocation)等这些步骤。

链接过程图示:在这里插入图片描述
源代码文件(.c)经过编译器编译成目标文件(.o或者.obj),目标文件和库(Library)一起链接形成可执行文件。

库:最常见的库使运行时库(Runtime Library),是支持程序运行的基本函数的集合。库其实是一组目标文件的包。

参考:《程序员的自我修养》

今天也要好好学习呀~

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鹿可可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值