【C语言】编译和链接

个人主页点这里~

本文篇幅较短,但内容在理解c语言内部逻辑方面却十分重要,希望大家能够认真的阅读

编译和链接

  • 一、翻译环境和运行环境
  • 二、翻译环境
    • 1、预处理
    • 2、编译
      • ①词法分析
      • ②语法分析
      • ③语义分析
    • 3、汇编
    • 4、链接
  • 三、运行环境

一、翻译环境和运行环境

在c语言的实现中,存在两个环境
翻译环境:在这个环境中源代码被转换成可执行的二进制指令
运行环境:实际执行代码

二、翻译环境

翻译由编译和链接两个过程组成
编译又可以分为预处理、编译、汇编三个过程
一个c语言的项目一般是由多个.c文件一起构建的,多个.c文件通过如下步骤生成可执行程序:
①多个.c文件单独经过编译器,编译处理生成对应的目标文件
②多个目标文件和链接库一起经过链接器处理生成最终的可执行程序
③链接库是指运行时库(支持程序运行的基本函数集合)或者第三方库
注意:在Windows环境下目标文件的后缀是.obj,Linux环境下的目标文件的后缀是.o
以下就是编译与链接的过程:

1、预处理

在预处理阶段,源文件和头文件都会被处理成为.i为后缀的文件
预处理阶段主要处理源文件中#开始的预编译指令,规则如下:
①将所有的#define删除,并展开所有的宏定义
②处理所有的条件编译指令
③处理 #include 预编译指令,将包含的头文件的内容插入到该预编译指令的位置。这个过程是递归进行的,因为包含的头文件可能包含其他文件
④删除所有的注释
⑤添加行号和文件名标识,方便后续编译器生成调试信息
⑥保留所有的 #pragma 的编译器指令,后续编译器会使用
经过预处理后的.i文件中不再包含宏定义,所有的宏定义已经被展开了,我们可以通过查看预处理后的.i文件来确认宏定义和头文件是否包含正确

2、编译

编译的过程就是将预处理后的文件进行语法词法的分析和优化,生成汇编代码

①词法分析

源代码程序会被输入扫描器,在扫描器中被简单词法分析,把代码中的字符分割开

arr[input] = (input+2)*(5-2);

这个代码是一个数组赋值代码,我们进行词法分析的时候会将它们全部拆开:

记号 类型
arr 标识符
[ 左方括号
input 标识符
] 右标识符
= 赋值
( 左圆括号
input 标识符
+ 加号
2 数字
) 右圆括号
* 乘号
( 左圆括号
5 数字
减号
2 数字
) 右圆括号

②语法分析

然后进入语法分析器,将分割开的字符记号进行语法分析,产生语法树(以表达式为结点的树)

③语义分析

然后进入语义分析器进行语义分析,也就是对表达式进行语法层面的分析,这个分析是静态分析,编译器能且只能做到静态分析,它通常包括声明和类型的匹配,类型的转换等,这个阶段会报告错误的语法信息

3、汇编

然后接下来一步是进入汇编器,将汇编指令转换为机器可执行的指令,根据汇编指令和机器指令的对照表一一翻译,不做指令优化

4、链接

然后就是链接,链接就是把一堆文件链接在一起生成可执行程序,它的过程主要包括:地址和空间的分配、符号决议、重定位等
重定位:当我们使用多个.c文件生成一个可执行程序的时候,由于编译的时候是每个文件单独编译的,当我们在一个文件中使用另一个文件定义的函数时,我们是需要明确地址的,这时我们会将地址暂时搁置,等到链接的时候再将地址修正,让它们的地址真正成为这个函数的地址,这个地址修正的过程,就叫做重定位

三、运行环境

1、程序必须载入内存当中:程序必须载入内存当中,在有操作系统的环境中,一般由这个操作系统来完成,在独立的环境中,需要手动操作,也可能是通过可执行代码置入只读内存完成
2、程序执行:程序执行便开始调用main函数
3、开始执行程序代码:开始执行程序代码时程序将使用一个运行时堆栈,存储函数的局部变量和返回地址,程序同时也可以使用静态内存,存储于静态内存中的变量在程序的整个执行过程一直保留它们的值
4、终止程序:正常终止main函数或意外终止

今日分享就到这里了~

版权声明:本文为博主作者:s_little_monster_原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/s_little_monster/article/details/137208007

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2024年4月16日
下一篇 2024年4月16日

相关推荐