当前位置: 首页 > news >正文

【C语言】编译与链接

✨✨欢迎大家来到Celia的博客✨✨

🎉🎉创作不易,请点赞关注,多多支持哦🎉🎉

所属专栏:C语言

个人主页:Celia's blog~

目录

 引言

一、翻译环境

1.1 编译

1.1.1 预处理

 1.1.2 编译

1.1.2.1 词法分析

1.1.2.2 语法分析

1.1.2.3 语义分析

1.1.3 汇编

1.2 链接

二、运行环境


 

 引言

  在C语言代码进行实现的时候,都存在两个不同的环境。一个是翻译环境,在这个环境中C语言的源代码会被翻译成可以执行的机器指令,也就是二进制指令。另一个是执行环境,用于执行这些被翻译后的机器指令。本篇文章将会详细介绍在翻译环境中所进行的一系列处理过程。

一、翻译环境

  翻译环境由编译链接两个过程所组成。在这其中,编译又可以分为预处理(预编译)、编译、汇编三个过程。

 在一个C语言的项目中,有可能会有多个.c文件,这些文件是如何生成可执行的程序的呢?

  • 多个.c文件会单独经过编译器,形成多个以.obj为后缀的目标文件(VS环境)。
  • 多个目标文件和链接库一起通过链接器,处理后形成后缀为.exe的可执行程序

 如果把编译拆分成三个过程,如下图所示(gcc编译器):

1.1 编译

1.1.1 预处理

  在这个过程中,源文件和头文件会被处理成为以.i为后缀的文件,在gcc编译器上,如果想进行该过程,指令如下:

gcc -E text.c -o text.i

 在预处理阶段,会进行以下操作:

  • 将所有的#define删除,并且展开所有的宏定义。
  • 处理所有的条件编译指令。(#if、#ifdef、#elef等)
  • 处理#include预编译指令,将该头文件所包含的所有内容插入到预编译指令所在的位置。这个过程中,如果头文件中包含了其他的头文件,将会递归进行展开。
  • 删除所有的注释信息。
  • 添加行号和文件名标识,以便后续的调试。
  • 保留所有的#pragma的编译器指令,以便后续使用。

 1.1.2 编译

  在该过程中,会对文件进行一系列的词法分析、语法分析、语义分析及优化,生成相应的汇编代码文件。

在gcc编译器上的指令:

gcc -S text.i -o text.s

 下面以一个例子来解释该过程:

array[index] = (index+4)*(2+6);
1.1.2.1 词法分析

  在该过程中,源代码程序会被输入到扫描器中,进行简单的词法分析,把代码中的字符分割成一系列的记号:

1.1.2.2 语法分析

  在该过程中,语法分析器会对扫描产生的记号进行语法分析,产生一个语法树,语法树是以表达式为节点的树。

1.1.2.3 语义分析

  该过程由语义分析器完成语义分析,是对表达式语法层面的分析(语义静态分析),语义静态分析通常包括:声明、类型的匹配、类型的转换等。这个阶段会报告错误的语法信息。

1.1.3 汇编

  汇编器会将汇编代码转换为机器可执行的机器指令,每一条汇编指令对应一条机器指令。这个过程是根据汇编指令和机器指令对照表一一进行翻译,不会做任何的优化。

在gcc编译器上的指令:

gcc -c text.s -o text.o

1.2 链接

  在这个过程中,会进行地址和空间的分配,符号决议重定位等步骤。目的是将一个项目中的多个文件链接在一起 ,形成可执行程序。

关于重定位:

如果我们在text.c文件中用到了其他文件中的变量或者函数,按道理来讲,需要明确这些在其他文件中的变量和函数的实际地址,才能够使用它们。但是因为每个文件都是单独编译的,text.c文件在被编译的时候并不知道其他文件中的变量和函数的地址,编译器会暂时搁置它们的地址。等到最后链接的时候,由链接器根据函数名或变量名,在其他的模块中寻找这些函数或者变量的地址,然后将之前搁置的地址重新修正,让这些暂时被搁置的地址变成真正的函数或变量的地址。这个暂时搁置地址在后期进行重新修正的过程就叫做重定位

二、运行环境

  • 程序一般必须载入内存中才能运行。在有操作系统的环境中,一般由这个操作系统来完成。 如果没有操作系统,程序的载入必须由手工安排,或者通过可执行代码置入只读内存来完成。
  • 程序运行后,进入main函数
  • 执行代码,使用运行堆栈储存局部变量和地址,也可使用静态内存。
  • 终止程序。正常终止main函数/异常终止。
http://www.lryc.cn/news/347314.html

相关文章:

  • Consul 注册的服务地址变成了 127.0.1.1
  • 数字水印 | 离散小波变换 DWT 的 Python 代码实现
  • [框架] Unity 公共执行器
  • 二进制转为HEX数组小工具
  • 数据结构-二叉树-红黑树
  • C++11 新特性 decltype 说明符
  • java线程局部变量使用方式
  • 【隧道篇 / WAN优化】(7.4) ❀ 01. 启动WAN优化 ❀ FortiGate 防火墙
  • 2024数维杯数学建模B题生物质和煤共热解问题的研究原创论文分享
  • 中国电子学会(CEIT)2022年12月真题C语言软件编程等级考试三级(含详细解析答案)
  • 今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 5月12日,星期日
  • 微服务思想以及实现
  • C语法:格式符号%f和%lf引发的错误
  • Java基础入门day48
  • C++笔记(体系结构与内核分析)
  • c++ 唤醒指定线程
  • java报错:使用mybatis plus查询一个只返回一条数据的sql,却报错返回了1000多条
  • AI图书推荐:利用生成式AI实现业务流程超自动化
  • 什么事防抖和节流,有什么区别,如何实现
  • PanguSync大数据量初始化脚本
  • DELL T630服务器iDRAC分辨率调整办法
  • 您真的会高效使用 Mac 吗?
  • Vue11 Vue3完结撒花
  • CodeTop 高频笔试题总结(持续更新)
  • 类和对象一(从封装开始讲述)
  • LeetCode100题总结
  • 基于截断傅里叶级数展开的抖动波形生成
  • 图片标注编辑平台搭建系列教程(9)——支持撤销的画线行为
  • 赶紧收藏!2024 年最常见 100道 Java 基础面试题(四十一)
  • 使用自关联方法处理多表关系