C语言编译与链接

前言

我们想一个问题,我们写的C语言代码都是文本信息,电脑能直接执行c语言代码吗?肯定不能啊,计算机能执行的是二进制指令,所以将C语言转化为二进制指令需要一段过程,这篇博客讲一下编译与链接,来一起探讨C语言是如何转化为二进制指令的。

个人主页:小张同学zkf

若有问题  评论区见

感兴趣就关注一下吧

目录

1. 翻译环境和运行环境

2. 翻译环境

2.1 预处理(预编译) 

 2.2 编译

 2.2.1 词法分析

 2.2.2 语法分析

 2.2.3 语义分析

2.3 汇编

 2.4 链接

3. 运行环境


1. 翻译环境和运行环境

在ANSI C(标准C)的任何一种实现中,存在两个不同的环境。
第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令(二进制指令)。
第2种是执行环境,它用于实际执行代码。


2. 翻译环境

那翻译环境是怎么将源代码转换为可执行的机器指令的呢?
这里我们就得展开开讲解一下翻译环境所做的事情。
其实翻译环境是由编译和链接两个大的过程组成的,而编译又可以分解成:预处理(有些书也叫预编译)、编译、汇编三个过程。

一个C语言的项目中可能有多个 .c 文 件一起构建,那多个 .c 文 件如何生成可执行程序呢?
多个.c文件单独经过编译器,编译处理生成对应的目标文件。
注: 在Windows环境下的目标文件的后缀是 .obj ,Linux环境下目标文件的后缀是 .o
多个目标文件和链接库一起经过链接器处理生成最终的可执行程序。
链接库是指运行时库(它是支持程序运行的基本函数集合)或者第三方库。
如果再把编译器展开成3个过程,那就变成了下面的过程:

2.1 预处理(预编译) 

在linux操作系统gcc环境下

在预处理阶段,源文件和头文件会被处理成为 .i 为后缀的文件。
gcc 环境下想观察一下,对 test.c 文 件预处理后的.i文件,命令如下:
gcc -E test.c -o  test.i

这个-E就是把在gcc环境下test.c 文件停留到预处理结束阶段用-o命令把此刻文件生成为test.i,所以,此刻文件就是预处理之后的文件。

预处理阶段主要处理那些源文件中#开始的预编译指令。如:#include,#define,处理的规则如下:
将所有的 #define 删除,并展开所有的宏定义。
处理所有的条件编译指令,如: #if #ifdef #elif #else #endif
处理#include 预编译指令,将包含的头文件的内容插入到该预编译指令的位置。这个过程是递归进行的,也就是说被包含的头文件也可能包含其他文件。
删除所有的注释
添加行号和文件名标识,方便后续编译器生成调试信息等。
或保留所有的#pragma的编译器指令,编译器后续会使用。
经过预处理后的.i文件中不再包含宏定义,因为宏已经被展开。并且包含的头文件都被插入到.i文件中。所以当我们无法知道宏定义或者头文件是否包含正确的时候,可以查看预处理后的.i文件来确认。

 2.2 编译

编译过程就是将预处理后的文件进行一系列的: 词法分析、语法分析、语义分析及优化 ,生成相应的汇编代码文件。
编译过程的命令如下:

 gcc -S test.i -o test.s

 就是把test.i文件进行-o处理,就是编译处理最后结果生成的文件为test.s

对下面代码进行编译的时候,会怎么做呢?假设有下面的代码

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

 2.2.1 词法分析

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

 2.2.2 语法分析

接下来 语法分析器 ,将对扫描产生的记号进行语法分析,从而产生语法树。这些语法树是以 表达式 为节点的树。

 2.2.3 语义分析

由语义分析器来完成语义分析,即对表达式的语法层面分析。编译器所能做的分析是语义的静态分 析。静态语义分析通常包括声明和类型的匹配,类型的转换等。这个阶段会报告错误的语法信息

注意:编译结束时,此刻的代码就是汇编代码 

2.3 汇编

编译完接下来一步就是汇编了,汇编就是把汇编代码生成机器指令

 gcc -c test.s -o test.o

把test.s进一步加工通过-o就是把这个文件汇编成test.o的文件,这时的文件就是目标文件。 此刻就是把c的源文件通过编译(预处理-编译-汇编)一个大步骤生成目标文件 

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

 2.4 链接

链接是一个复杂的过程,链接的时候需要把一堆目标文件链接在一起才生成可执行程序。
链接过程主要包括:地址和空间分配,符号决议和重定位等这些步骤
链接解决的是 一个项目中多文件、多模块之间互相调用 的问题。
我们已经知道,每个源文件都是单独经过编译器处理生成对应的目标文件。
test.c 经过编译器处理生成 test.o
add.c 经过编译器处理生成 add.o
我们在 test.c 的文件中使用了 add.c 文 件中的 Add 函数
我们在 test.c 文 件中每一次使用 Add 函数的时候必须确切的知道 Add 的地址,但是由于每个文件是单独编译的,在编译器编译 test.c 的时候并不知道 Add 函数变量的地址,所以暂时把调用 Add 的指令的目标地址搁置, 等待最后链接的时候由链接器根据引用的符号 Add 在其他模块中查找 Add 函数的地址,然后将 test.c 中所有引用到Add 的指令重新修正,让他们的目标地址为真正的 Add 函数的地址, 这个地址修正的过程也被叫做: 重定位
链接结束后,就生成了我们想要的 可执行程序

3. 运行环境

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

结束语

本篇博客总结了编译和链接涉及C语言的有关知识,其实很多内部的细节无法展开总结。比如:目标文件的格式elf,链接底层实现中的空间与地址分配,符号解析和重定位等,如果有兴趣,可以看《程序的自我修养》一书和我的博客搭配着来详细了解这方面的知识。

OK感谢观看!!!

下片博客见

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

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

相关文章

Day26 手撕各种集合底层源码(一)

Day26 手撕各种集合底层源码(一) 一、手撕ArrayList底层源码 1、概念: ArrayList的底层实现是基于数组的动态扩容结构。 2、思路: 1.研究继承关系 2.研究属性 3.理解创建集合的过程 – 构造方法的底层原理 4.研究添加元素的过程…

vue实现把Ox格式颜色值转换成rgb渐变颜色值(开箱即用)

图示: 核心代码: //将0x格式的颜色转换为Hex格式,并计算插值返回rgb颜色 Vue.prototype.$convertToHex function (colorCode1, colorCode2, amount) {// 确保输入是字符串,并检查是否以0x开头let newCode1 let newCode2 if (t…

关系型数据库mysql(5)存储引擎

目录 一.存储引擎的概念 二. MyISAM 和 InnoDB 2.1MyISAM介绍 2.2MyISAM支持的存储格式 2.2.1静态表(固定长度表) 2.2.2动态表 2.2.3压缩表 2.3场景举例 2.4.InnoDB 2.4.1场景举例 2.4.2企业选择存储引擎依据 三.查看存储引擎 3.1查看当前数…

C++中的STL简介与string类

目录 STL简介 STL的版本 STL的六大组件 string类 标准库中的string类 string类的常用接口 string类对象对容量的操作 size()函数与length()函数 capacity()函数 capacity的扩容方式 reserve()函数 resize()函数 string类对象的操作 push_back()函数 append()函数 operator()函数…

【01-20】计算机网络基础知识(非常详细)从零基础入门到精通,看完这一篇就够了

【01-20】计算机网络基础知识(非常详细)从零基础入门到精通,看完这一篇就够了 以下是本文参考的资料 欢迎大家查收原版 本版本仅作个人笔记使用1、OSI 的七层模型分别是?各自的功能是什么?2、说一下一次完整的HTTP请求…

记录何凯明在MIT的第一堂课:神经网络发展史

https://www.youtube.com/watch?vZ5qJ9IxSuKo 目录 表征学习 主要特点: 方法和技术: LeNet 全连接层​ 主要特点: 主要特点: 网络结构: AlexNet 主要特点: 网络结构: Sigmoid Re…

经典永不过时 Wordpress模板主题

经得住时间考验的模板,才是经典模板,带得来客户的网站,才叫NB网站。 https://www.jianzhanpress.com/?p2484

第十五届蓝桥杯第三期模拟赛第十题 ← 上楼梯

【问题描述】 小蓝要上一个楼梯,楼梯共有 n 级台阶(即小蓝总共要走 n 级)。小蓝每一步可以走 a 级、b 级或 c 级台阶。 请问小蓝总共有多少种方案能正好走到楼梯顶端?【输入格式】 输入的第一行包含一个整数 n 。 第二行包含三个整…

vulfocus环境搭建(kali搭建)

Vulfocus 是一个漏洞集成平台,将漏洞环境 docker 镜像,放入即可使用,开箱即用。 安装docker环境 个人不建议随意更换apt源,我换了几次遇到很多问题。 apt-get update apt-get upgrade(时间很久) apt-get i…

基于springboot的人事管理系统

人事管理系统 摘 要 人事管理系统理工作是一种繁琐的,务求准确迅速的信息检索工作。随着计算机信息技术的飞速发展,人类进入信息时代,社会的竞争越来越激烈,人事就越显示出其不可或缺性,成为学校一个非常重要的模块。…

防止恶意软件和网络攻击的简单贴士

如今,缺少互联网的生活是难以想象的。然而,互联网的匿名性导致了网络攻击和恶意软件很猖獗。恶意软件会损坏我们的设备、窃取个人数据,并导致金钱损失。因此,保护计算机免受这些威胁显得至关重要。 一、确保操作系统和软件是最新版…

企业数据资产管理的战略价值与实施策略

一、引言 数据资产不仅记录了企业的历史运营情况,更能够揭示市场的未来趋势,为企业的决策提供有力支持。因此,如何有效地管理和利用数据资产,已经成为企业竞争力的重要体现。本文将探讨企业数据资产管理的战略价值与实施策略&…

URL编码:原理、应用与安全性

title: URL编码:原理、应用与安全性 date: 2024/3/29 18:32:42 updated: 2024/3/29 18:32:42 tags: URL编码百分号编码特殊字符处理网络安全应用场景标准演变未来发展 在网络世界中,URL(统一资源定位符)是我们访问网页、发送请求…

设计模式之单例模式精讲

UML图: 静态私有变量(即常量)保存单例对象,防止使用过程中重新赋值,破坏单例。私有化构造方法,防止外部创建新的对象,破坏单例。静态公共getInstance方法,作为唯一获取单例对象的入口…

速通汇编(二)汇编mov、addsub指令

一,mov指令 mov指令的全称是move,从字面上去理解,作用是移动(比较确切的说是复制)数据,mov指令可以有以下几种形式 无论哪种形式,都是把右边的值移动到左边 mov 寄存器,数据&#…

AI 创新领跑者,KIP Protocol 如何理解 Decentralized AI

随着 OpenAI 的 Sora 推动 AI 赛道的热度攀升,AI 领域再次成为科技和投资界的焦点。KIP Protocol 是面向 AI 模型制作者、App 开发者和数据所有者构建的去中心化 Web3 协议层,使数据可在 Web3 中安全地进行交易和货币化。KIP Protocol 由 Animoca Ventur…

Jenkins实现CICD

Jenkins实现CICD JenkinsCI简介环境安装新建任务源码管理构建配置发送邮件配置自动化项目定时构建 JenkinsCD简介配置ssh保证其可以免登录接下来配置github的webhook正式实现自动化打包master主分支的代码将前端三剑客代码文件发送到网站服务器对应的tomcat Jenkins面试题 Jenk…

个人简历主页搭建系列-04:网站初搭建

准备工作差不多了,该开始搭建网站了! 这次我们先把网站搭建部署起来,关于后续主题内容等更换留到后续。 创建源码文件夹 首先通过 hexo 创建本地源码文件夹。因为最终部署的 github 仓库格式为 websiteName.github.io(websiteN…

Gartner发布新兴技术指南:生成式人工智能和深度伪造对身份验证的影响

使用生成式人工智能(GenAI)技术生成的 Deepfakes(深度伪造) 对身份验证的完整性构成了根本威胁。身份验证产品领导者必须了解这一新兴威胁,并采取积极主动的方法来区分和保护其解决方案产品。 主要发现 活体检测技术对于防御深度伪造以及在身…

【每日力扣】332. 重新安排行程与51. N 皇后

🔥 个人主页: 黑洞晓威 😀你不必等到非常厉害,才敢开始,你需要开始,才会变的非常厉害。 332. 重新安排行程 给你一份航线列表 tickets ,其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你…