初识编译和链接(C语言)

文章目录

  • 编译和链接
    • 翻译环境
      • 预处理
      • 编译
      • 汇编
      • 链接
    • 运行环境

编译和链接

编译和链接这两个大的过程构成了翻译环境。

其实,在ANSI C的任何一种实现中,存在两个不同的环境。

一个环境是翻译环境,另一个是执行环境。
翻译环境中,源代码被转换为可执行的机器指令。
执行环境中,代码将被实际执行。

这两大环境就是要介绍的内容,不过较多介绍的是翻译环境。

翻译环境

上面介绍,翻译环境中,源代码被转换为可执行的机器指令,怎么做的?

编译 + 链接

在这里插入图片描述

  • 编译器和链接器就是一个可执行程序,所以以 .exe为后缀

  • Windows环境下的目标文件后缀是 .obj,Linux环境下目标文件后缀是 .o

  • 链接库是指运行时库(它是支持程序运行的基本函数集合)或者第三方库。

我们讲的编译其实是三个过程的统称,这三部分是:预处理(预编译)、编译、汇编

1. 如果有多个.c文件,那么每个文件会单独经过编译器,编译处理生成对应目标文件。
2. 多个目标文件和链接库一起经过链接器处理生成最终的可执行程序。

将这个过程展开:

在这里插入图片描述

接下来,我们将这三个过程逐个介绍:

预处理

预处理阶段,源文件、头文件会被处理成 .i为后缀的文件。

预处理阶段主要处理源文件中#开始的预编译指令。比如:#include、#define,处理的规则如下:

  • 删除所有的 #define,展开所有的宏定义(本质是替换)
  • 处理条件编译指令,例如:#if#elif
  • 处理 #include预编译指令,将包含的头文件的内容插入到预编译指令的位置。这个过程是递归进行的,也就是说被包含的头文件可能包含其他文件。
  • 删除所有注释
  • 添加行号和文件名标识,方便后续编译器生成调试信息等
  • 保留所有的 #pragma的编译器指令,编译器后续会使用。

预处理最终生成 .i文件中不再包含宏定义,宏已经被展开。


编译

编译过程是将预处理后的文件执行:词法分析、语法分析、语义分析及优化,生成相应的汇编代码文件。

对下面例子编译过程进行分析

array[index] = (index+4)*(2+6);

词法分析

源代码程序被输入扫描器,扫描器的任务就是简单的进行词法分析,把代码中的字符分割成一系列的记号(关键字、标识符、字面量、特殊字符)。

在这里插入图片描述

语法分析

接着对扫描产生的记号进行语法分析,产生语法树。这些语法树是以表达式为结点的树。

在这里插入图片描述

语义分析

语义分析器来完成语义分析,即对表达式的语法层面分析。编译器所能做的分析是语义的静态分析。静态语义分析通常包括声明和类型的匹配,类型的转换等。

在这里插入图片描述


汇编

汇编器是将汇编代码转变为机器可执行的指令,每一个汇编语句几乎都对应一条机器指令。就是根据汇编指令和机器指令的对照表一一的进行翻译,也不做指令优化。


链接

链接是一个复杂的过程,链接的时候需要把一堆文件链接到一起才生成可执行程序。

链接过程主要包括:地址和空间分配,符号决议和重定位等这些步骤。

链接能解决一个项目中多文件、多模块之间互相调用的问题。

例如这样一个项目,有两个 .c文件

在这里插入图片描述

//test.c
#include <stdio.h>
extern int n;
extern int add(int x, int y);int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);printf("%d\n%d", add(a, b), n);return 0;
}
//add.c
int n = 100;int add(int x, int y)
{return x + y;
}

输入20 和 30,程序正常运行:
在这里插入图片描述

前面介绍了,多个.c文件是单独编译的,并生成各自对应的目标文件。

test.c文件中使用了add.c文件中的add函数和n变量

我们在test.c⽂件中每⼀次使用 add 函数和n的时候必须确切的知道 addn 的地 址,但是由于每个⽂件是单独编译的,在编译器编译 test.c 的时候并不知道 add 函数和变量 n 的地址,所以会暂时把调⽤ add 的指令的目标地址和 n 的地址搁置。等待最后链接的时候由链接器根据引用的符号 add 在其他模块中查找 add 函数的地址,然后将 test.c 中所有引用到 add 的指令重新修正,让他们的目标地址为真正的 add 函数的地址,对于全局变量 n 也是类 似的方法来修正地址。这个地址修正的过程也被叫做:重定位

运行环境

运行环境是由英语的“runtime environment”直译,意指一种把半编译的执行码在目标机器上运行的环境。

由翻译环境生成的后缀为 .exe的可执行程序将会在运行环境实际运行。

  • 程序运行时必须载入内存。在有操作系统的环境中,一般这个由操作系统完成。独立环境中,程序载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
  • 载入内存后,程序开始执行,调用main函数。
  • 程序将使用一个运行时堆栈,存储函数的局部变量和返回地址。程序同时可以使用静态内存,存储静态内存中的变量,并在整个执行过程中一直保留它们的值。
  • 最后终止程序。当然会有意外终止的情况。

以上就是今天分享的内容,知识较为浅薄,没有深入,不过一定程度上弥补了一些知识盲区,后面会发布一篇有关预处理的博客,希望大家多多支持。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/784971.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【软件工程】详细设计(一)

1. 引言 1.1 编写目的 该文档的目的是描述《学生成绩管理系统》项目的详细设计&#xff0c;其主要内容包括&#xff1a; 系统功能简介 系统详细设计简述 各个模块的实现逻辑 最小模块组件的伪代码 本文档的预期的读者是&#xff1a; 开发人员 项目管理人员 测试人员 …

基于单片机汽车超声波防盗系统设计

**单片机设计介绍&#xff0c;基于单片机汽车超声波防盗系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机汽车超声波防盗系统设计概要主要涉及利用超声波传感器和单片机技术来实现汽车的安全防盗功能。以下是对…

八股 -- C#

面向对象 &#xff08;三大特性&#xff09; 三大特性目的是为了提供更好的代码组织、可维护性、扩展性和重用性 C#基础——面向对象 - 知乎 (zhihu.com) 封装 理解&#xff1a; 你不需要了解这个方法里面写了什么代码&#xff0c;你只需要了解这个方法能够给你返回什么数据&…

位运算 ----力扣2220

2220. 转换数字的最少位翻转次数 提示 一次 位翻转 定义为将数字 x 二进制中的一个位进行 翻转 操作&#xff0c;即将 0 变成 1 &#xff0c;或者将 1 变成 0 。 比方说&#xff0c;x 7 &#xff0c;二进制表示为 111 &#xff0c;我们可以选择任意一个位&#xff08;包含没有…

书生·浦语大模型-第一节课笔记

视频总结 23年发布的模型在一些材料中归位指令微调模型&#xff0c;后面逐渐升级应该已经是train的模型了 技术报告总结 InternLM2 Technical Report 评测与特点 6 dimensions and 30 benchmarks, long-context modeling, and open-ended subjective evaluations长文本…

猜数游戏(Python)

一、实验要求&#xff1a; &#xff08;1&#xff09;在游戏开始时&#xff0c;随机生成一个1~100之间的整数。 &#xff08;2&#xff09;在游戏中&#xff0c;玩家有10次机会猜数。如果10次都没有猜中&#xff0c;则游戏失败&#xff1b;否则&#xff0c;游戏成功。 &…

centos7.5安装gitlab-runner,配置CI/CD流水线

一般不建议gitlab-server和gitlab-runner装在同一台服务器 第一步&#xff1a;安装gitlab-runner,最好和gitlab实例版本一致 # 下载官方gitlab-runner安装脚本 curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh" | s…

成为一名自由程序员

越来越多的程序员已经或希望加入到自由职业者的行列&#xff0c;你是否也是其中的一员呢&#xff1f;在这篇文章里我将尝试结合自身的一些经验&#xff0c;来告诉你成为自由程序员能够获得的那些益处&#xff0c;以及为了取得成功所需要面临的挑战。 自由程序员的类型 很多人把…

项目开发---用户登录发送短信实现(使用阿里云短信接口)(看这篇就够了)

目录&#xff1a; 使用阿里云开通短信服务教程编写代码 使用阿里云开通短信服务教程 阿里云官网&#x1f449;https://cn.aliyun.com/ 完成登录 进入短信服务 开通短信服务 购买短信条数 购买完成进入阿里云短信控制台https://dysms.console.aliyun.com/overview 开通个…

Taskflow应用:波前并行(Wavefront Parallelism)

2D的Wavefront如下图所示&#xff1a; #include <taskflow/taskflow.hpp>std::mutex cout_mutex; void format_str(std::string const& str) {std::lock_guard<std::mutex> lock(cout_mutex); std::cout << str << std::endl; }std::string crea…

《自动机理论、语言和计算导论》阅读笔记:p68-p114

《自动机理论、语言和计算导论》学习第4天&#xff0c;p68-p114总结&#xff0c;总计47页。 一、技术总结 1.inverted indexes 明白单词的意思是“反转的索引”&#xff0c;但是不明白其在书中具体指什么&#xff0c;去查询资料的话需要花很不多时间&#xff0c;先继续往下看…

关于使用vscode搭建c/c++编程环境

目录 关于使用vscode搭建c/c编程环境一、前言二、安装 IDE 二、安装TDM-GCC安装三、安装C/C环境四、编写代码并进行编译 关于使用vscode搭建c/c编程环境 一、前言 一直觉得vscode是生产强有力的生产工具&#xff0c;基于此&#xff0c;做一篇学习笔记进行记录。 二、安装 ID…

服务器停止解析域名,但仍然可以访问到

1.centos7 如何刷新dns缓存 在CentOS 7上&#xff0c;DNS缓存由nscd&#xff08;Name Service Cache Daemon&#xff09;管理&#xff0c;如果系统上安装了nscd&#xff0c;可以通过清除nscd缓存来刷新DNS缓存。 要刷新DNS缓存&#xff0c;请执行以下命令&#xff1a; sudo …

IPD推行成功的核心要素(一)什么企业需要和适合IPD?

IPD&#xff0c;全称为“Integrated Project Delivery”&#xff0c;即集成产品开发。它是一种全新的项目管理方法&#xff0c;目前已经应用到了各行各业的项目管理中。IPD是一种以协同合作为核心的工作模式&#xff0c;在这种模式下&#xff0c;项目中的所有相关方在项目的整个…

如何使用免费的ChatGpt3.5

如何使用免费的ChatGpt 最近免费的gpt3.5很多都不怎么行了实在是太给力了尾声 最近免费的gpt3.5很多都不怎么行了 原因是什么呢&#xff1f;因为openai已经取消了免费的5刀赠送&#xff0c;那么这些人手上的免费的sses-key 用完后&#xff0c;就基本上全军覆没了&#xff0c;再…

校园招聘管理系统(源码+文档)

校园招聘管理系统&#xff08;小程序、ios、安卓都可部署&#xff09; 文件包含内容程序简要说明含有功能项目截图客户端热门岗位校园招聘首页个人简历添加个人简历我的界面注册界面查看个人简历界面个人资料界面登录界面消息界面退出登录 管理端登录界面![请添加图片描述](htt…

Python保留字与obspy安装

保留字&#xff1a; 被编程语言内部定义并保留使用的标识符。Python有33个保留字 andelifimportraiseglobalaselseinreturnnonlocalassertexceptistryTrue breakfinallylambdawhileFalseclassfornotwithNonecontinuefromoryielddefifpassdel 最近在安装obspy时经常&am…

预处理指令——那些你可能不知道的概念

前言&#xff1a;预处理是我们的c语言源代码成为可执行程序的第一个步骤。而宏和预处理指令都是在这个阶段完成。本节内容就是关于宏和预处理指令相关知识点的解析。 目录 宏 预定义符号 #define定义常量 #define定义符号 #define定义宏 带副作用的宏参数 宏的替换规则…

给虚拟机配置静态IP并使用FileZIlla在虚拟机和Windows之间传输文件(ssh和ftp两种方法)

一、配置操作系统网络 &#x1f338;下面的步骤主要是配置虚拟机的静态IP&#xff0c;方便后续用 FikeZilla 在windows和虚拟机之间传输文件&#xff08;否则用默认的ip分配方案为 DHCP ,每一次开机时的ip都是有可能不同的,这样就会导致每次远程连接都需要查看ip地址.&#xf…

mysql执行脚本导入表和数据后中文注释乱码解决

本人在使用不同版本下进行操作时&#xff0c;就会出现中文乱码的问题。例如我本地安装mysql8&#xff0c;服务器安装的是mysql5&#xff0c;然后本地连接服务器的mysql后&#xff0c;执行SQL脚本之后发现中文全部乱码 使用工具查看&#xff0c;注释也都是乱码 解决方案 本地…