【C语言】编译和链接(细节的king)

news2024/11/15 23:19:24

文章目录

  • 前言
  • 1. 翻译环境和运行环境
    • 1.1 翻译环境
      • 1.1.1 预处理(预编译)
      • 1.1.2 编译
        • 词法分析
        • 语法分析
        • 语义分析及优化
      • 1.1.3 汇编
      • 1.1.4 链接
    • 1.2 运行环境

前言

相信大家在学完C语言的全部基础知识,肯定会经常动手敲代码。以VS为例,大家在使用IDE进行编译代码时,有没有想过编译的过程中发生了什么?为什么一定要包含stdio.h这个头文件?以及编译器是如何识别出我们头文件并且加入到我们的代码中的?

这些问题都会随着本文的讲解,大家的脑海就会逐渐出现一个清晰的认知了。

1. 翻译环境和运行环境

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

第一种是翻译环境,在这个环境中源代码会被转换为机器所能够识别的机器指令(二进制指令)。
第二种是运行环境,它是用于实际代码的执行。

不难想象,多个.c源文件经过编译器的编译和链接器的链接之后,生成的目标文件(.obj)。在经过运行环境下生成可执行文件(.exe),并生成结果。

1.1 翻译环境

那翻译环境是如何将代码翻译成机器能够识别的机器指令的呢?这里我们就要笼统地展开讲解一下翻译环境所做的事情了。

其实翻译环境是由编译和链接这两个步骤所组成的,而编译又分为预处理(有些书也会成为预编译)、编译和汇编三个过程。

一个C语言的项目中可能有多个.c源文件一起构建,那么编译器是如何把多个.c的源文件给组合到一起最终生成可执行程序的呢?

  • 每个.c的源文件会单独经过编译器的处理,编译生成对应的目标文件。
  • 注意:在Windows环境下的目标文件后缀为.obj,在Linux环境下的目标文件后缀为.o
  • 链接器会将生成的多个目标文件和链接库给链接起来,最终生成可执行程序。
  • 链接库是指运行时库(它是支持程序运行的基本函数集合)或者第三方库。

1.1.1 预处理(预编译)

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

gcc -E test.c -o test.i

由于VS的编译器不是gcc,这里我就用vscode给大家展示预处理之后的文件。

预处理

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

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

经过预处理之后的.i 文件里就不再包含宏定义,因为宏都已经被展开了。并且包含的头文件的内容都会插入到.i文件中。所以当我们不知道宏或者头文件有无正确包含时,可以来查看.i文件。

1.1.2 编译

编译的过程其实就是对预处理之后的文件进行一系列的词法分析,语法分析以及语义分析及优化

查看编译过程结束之后文件的命令:

gcc -S test.i -o test.s

汇编文件
test.s中的内容其实是汇编代码,看不懂是正常的。

思考一个问题:
假设对下面的代码进行编译时,会怎么做呢?

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

将源代码程序输入到扫描器中,扫描器的任务就是简单地对代码进行词法分析。

词法分析是到底在做一件什么事?
词法分析就是通过扫描器把代码中的字符分割成一系列的记号(关键字、标识符、字面量、特殊字符等)。

如果对上面代码进行词法分析,就会产生16个符号:

记号类型
array标识符
[左方括号
index标识符
]右方括号
=赋值
(左圆括号
index标识符
+加号
4数字
)右圆括号
*乘号
(左圆括号
2数字
+加号
6数字
)右圆括号
语法分析

讲完了扫描器的作用,接下来讲一下语法分析器

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

语法树

语义分析及优化

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

1.1.3 汇编

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

汇编的命令如下:

gcc -c test.s -o test.o

1.1.4 链接

链接是一个复杂的过程,链接的时候需要把程序运行所需要的所有文件都给关联在一起之后才生成可执行程序。

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

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

想要了解更加详细的内容,推荐大家看一下这本书《程序员的自我修养》。

1.2 运行环境

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

至此,本文就讲解结束了。如果觉得本文讲的好不错的话,麻烦给偶点个赞吧!

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

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

相关文章

【C++】—— 类与对象(三)

【C】—— 类与对象(三) 4、拷贝构造函数4.1、初识拷贝构造4.1.1、为什么要传引用4.1.2、引用尽量加上 const 4.2、深入拷贝构造4.2.1、为什么要自己实现拷贝构造4.2.2、传值返回先调用拷贝构造的原因4.2.3、躺赢的 MyQueue4.2.4、传值返回与引用返回 4.…

云HIS,云HIS源码

医学领域的信息系统平台种类繁多。在很大程度上,对于一些在医疗机构的区域一体化信息平台,在微观层面上,传统的医疗信息系统已经建立了许多医院(HIS)或数字医院系统,包括子系统提供了一个单一的功能,如注册和形象&…

【H3C(HCL)网络模拟器网络桥接】进入网络设备Web页面

H3C模拟器网络桥接 1.模拟器选择Host,添加 2.选中Host主机的网卡,这里我选的是华三的Virtual Box的网卡 选中后连线至防火墙对应接口,建议连接到G1/0/1,这个接口是默认配置的接口,拥有默认地址 3.修改防火墙配置 [F…

Windows 中 PIN 和密码的区别是什么?各有各的优点

PIN PIN 即个人识别号码(Personal Identification Number),在 Windows 系统中通常由 4 到 6 位数字组成。它是 Windows Hello 的一部分,设计用于提供快速、安全的身份验证。 密码 密码是一种更为传统的身份验证方法,…

提升生产效率:APS高级计划排程系统在车间工序级排程的革命性应用

在制造业的数字化转型浪潮中,APS高级计划排程系统以凭借自身卓越的排程运算能力和应用灵活性,已经成为中大型制造业提升生产效率的关键工具。APS系统的介入,打通了传统ERP和MES等各类业务系统运营平台,并且通过产能均衡规划&#…

聚观早报 | 搜狐2024年Q2财报;一加Open推出深红色版本

聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 8月6日消息 搜狐2024年Q2财报 一加Open推出深红色版本 smart精灵#5将在澳洲首秀 OpenAI为ChatGPT测试文本水印 …

手动部署内网穿透

关于内网穿透,主要针对什么是公网和内网?NAT转化技术等引出内网穿透方法。 本文主要技术是利用frp部署内网穿透、以及nagix部署web服务。 测试环境: 服务器:Linux云服务内网:用本地WM充当内网云服务器Linux&#xf…

伯克利Linux系统管理: 脚本编写学习 课堂与实验(系统简洁保姆级学习)

Linux系列文章目录 补充内容 Windows通过SSH连接Linux 第一章 Linux基本命令的学习与Linux历史 第二章(上) Vim课堂与实验 文章目录 Linux系列文章目录一、前言二、学习内容:2.1 上课内容2.1.1 为什么要学习脚本编写?2.1.2 Bash编程语言2.1.3 SheBang2.…

半导体PEEK纳米级钻孔,用德国高精密主轴

在半导体行业,对精度、效率与稳定性的要求近乎苛刻。其中,PEEK(聚醚醚酮)材料因其优异的耐热性、耐化学性和机械性能,在高端半导体封装、微流控芯片等领域得到了广泛应用。然而,PEEK材料的硬度与韧性并存&a…

Armv8/Armv9的Pstate寄存器介绍

PSTATE概述 在Armv7及其之前,有一个重要的寄存器叫做程序状态寄存器CPSR,但是到了Armv8/Armv9的aarch64架构时,删除了CPSR寄存器,改为了PSTATE(PE状态寄存器)。 PSTATE表示一组小寄存器的集合,…

隐私指纹浏览器产品系列 — 什么是指纹(一)

1.引言 现在许多网站在努力的尝试标记互联网上的每一个访客,用以追踪用户的行为轨迹,分析行为习惯,以及确认是否为真实用户。除此之外,他们还利用这些标记,将多个可能是同一个用户身份的访客进行归一,关联…

中国高尔夫运动快速发展中,深圳高尔夫展邀您迎接机遇与挑战

在浩瀚的体育世界中,高尔夫以其悠久的历史、优雅的姿态和独特的魅力闻名于世,被誉为“古老的贵族运动”,而这个美誉却让很多人对它敬而远之。其实高尔夫被称作“贵族运动”,仅仅是因为早期它更多在贵族之间流行而已。 高尔夫&…

【TS】基本类型

基本类型 类型例子描述number1, -33, 2.5任意数字stringhi, "hi", hi任意字符串booleantrue、false布尔值true或false字面量其本身限制变量的值就是该字面量的值any*任意类型unknown*类型安全的anyvoid空值(undefined)没有值(或und…

鸿蒙HarmonyOS开发:如何使用第三方库,加速应用开发

文章目录 一、如何安装 ohpm-cli二、如何安装三方库1、在 oh-package.json5 文件中声明三方库,以 ohos/crypto-js 为例:2、安装指定名称 pacakge_name 的三方库,执行以下命令,将自动在当前目录下的 oh-package.json5 文件中自动添…

面对电商渠道品牌要如何控价

在当今竞争激烈的市场环境中,品牌销售渠道的管理至关重要。线上和线下渠道的低价、窜货问题犹如侵蚀品牌根基的蚁穴,若不加以有效治理,品牌价值将受到严重损害。 线上渠道方面,除了利用系统精准监测低价情况外,还应注重…

手撕数据结构之二叉树

1.树 树的基本概念与结构 树是⼀种⾮线性的数据结构,它是由 n(n>0) 个有限结点组成⼀个具有层次关系的集合。把它叫做树是因为它看起来像⼀棵倒挂的树,也就是说它是根朝上,⽽叶朝下的。 • 有⼀个特殊的结点&…

python语言day2

字符串: 字符串的方法 字符串格式化: 输出结果: 姓名张三今年123岁,现在在北京工作,名字叫张三 text "姓名{0}今年{1}岁,现在在{2}工作,名字叫{0}".format("张三",123,"北京") print(t…

关于冒泡算法

一、前言 当谈及经典排序算法时,冒泡排序(Bubble Sort)无疑是最具代表性的一种。这种算法以其简单直观的特点,成为初学者理解排序基本概念的理想选择。本文将深入解析冒泡排序的原理、实现步骤,以及其在 C# 编程中的具…

【Vue】RuoYi-Vue 若依 vue3 版本安装 tailwindcss 不生效问题

解决方法 删除默认安装教程下的 postcss.config.js 将配置转移到 vite.config.js 中,不生效原因我推测是因为 vite.config.js 配置 postcss 这段覆盖了 postcss.config.js 所致 代码修改如下: 另外原博主友情提示,引入的TailwindCSS的样式…

已解决AttributeError: module ‘emoji‘ has no attribute ‘get_emoji_regexp‘

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…