初识C语言·编译与链接

news2025/1/18 18:46:00

1 翻译环境和运行环境

C语言标准ANSI C 实现C语言代码的时候 一般需要经过两种环境,一是翻译环境,二是运行环境,计算机能识别的是二进制的指令,人写完代码后通过翻译环境,使代码变成计算机能读懂的可执行的机器指令,运行环境就是用来执行实际的代码操作的环境。

1)翻译环境

那么翻译环境如何让源代码变成可执行的机器指令的呢?

翻译环境包含的是编译链接两大过程,其中编译包含预处理(也可以叫做预编译),编译,汇编

编译的时候,机器通过编译器使.c文件生成.obj文件,.obj文件是目标文件(在windows是.obj为后缀,Linux环境下是.o为后缀),多个目标文件在经过链接库的处理,最后生成 .exe文件

VS2022用到的编译器是cl.exe:

用到的链接器是link.exe:

编译的整个过程如下:(Linux下的gcc编译器为例)
.c文件 .h文件 源文件 经过预处理 生成.i为后缀的文件  ->  经过编译生成.s为后缀的文件 -> 经过汇编生成.o为后缀的文件 -> 经过链接器和链接库生成最后的可执行文件.exe

预处理:

在gcc环境下,我们使用指令:

gcc -E test.c -o test.i

使机器生成.i为后缀的文件的时候,我们就会发现代码出现了一下改变,这里因为在预处理阶段,存在以下规则:
1 删除所有的#define,所有宏定义被展开

2 处理所有的条件编译指令,如#endif #if #else

3 处理#include预编译指令,将头文件里面包含的内容插入到头文件所在的位置,这个过程是递归进行的,不排除头文件里面包含其他头文件的可能性

4 所有的注释都会被删除

5 或保留#pragma指令,编译器后续会使用,为了防止头文件重复包含

6 添加行号和文件名标识,方便编译器后续生成调试信息

当我们不知道宏定义是否包含正确的时候就可以经预处理之后的.i文件进行确认。

编译:

在gcc环境下,我们使用指令:

gcc -S test.i -o test.s

使机器生成了.s为后缀的文件,在这个阶段,编译器会进行三个操作,词法分析语法分析语义分析及优化

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

假定以上代码

词法分析:

词法分析就是把代码中的字符分隔开,分割成一系列的记号,如关键字,标识符,特殊字符,字面常量,如下:

语法分析

通过词法分析产生的记号,语法分析器通过记号生成语法树,以表达式为结点的树,如下:

语义分析
语义分析器会从表达式的层面分析,能做的分析使语义的静态分析,静态语义分析包括通常包括声明和类型的匹配,类型的转化等,这个阶段会显示错误的语法信息。

汇编:

汇编的指令如下:

gcc -c test.s -o test.o

汇编器将汇编代码变成机器可以执行的指令,每一个汇编语句几乎都对应一个机器指令,而汇编语言较难的一个原因就是不同的机器的汇编语言是不一样的,不具有跨平台性。

链接:

链接是一个复杂的过程,需要将一堆文件链接在一起才能生成可执行程序。

链接包括分配地址,分配空间,符号决议,重定位,等步骤。

链接解决的是一个项目中多文件多模块互相调用的问题,比如一个C语言的项目中有两个.c文件(test.c add.c)

extern int Add(int, int);//声明外部函数
extern int g_val;//声明外部全局变量
int main()
{
	int a = 10, b = 20;
	int sum = Add(a, b);
	printf("%d ", sum);
	printf("g_val = %d ", g_val);
	return 0;
}
int g_val  = 2024;
int Add(int x,int y)
{
    return x + y;
}

test.c 经过编译器处理生成了test.o文件,Add.c经过编译器处理生成了Add.o文件,通过关键字extern我们在test.c文件里面使用了函数Add 和 全局变量g_val,但是每一次使用这两个外部符号的时候必须确切的知道Add g_val的地址,因为编译器是单独编译的,所以编译器编译test.c文件的时候并不知道函数Add g_val的存在,所以暂时调用Add的指令的目标地址和g_val的地址搁置,等最后链接的时候根据引用的符号Add在其他模块寻找Add函数的地址,最后修正test.c文件里面引用到的Add的地方,使目标地址成为真正的函数Add的地址,对于全局变量亦是如此,这个修正的过程叫做重定义

2)运行环境:

运行环境就没什么好介绍的了:
程序运行的时候必须载入到内存里面,在有操作系统的环境下,一般都是由操作系统完成,独立的环境下,程序的载入必须通过手工安排。因为程序运行的时候操作系统会为程序开辟函数栈帧,调用堆栈,所以载入内存是必须的。

最后就是终止程序了,可能是main函数顺利读取到了最后一行,也可能是意外终止,比如按下F11的时候调试到一般关闭程序,这时候程序就会显示返回值是-1,也就是意外终止了。


感谢阅读!

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

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

相关文章

伦敦金重点知识:控制亏损的方法

在很多人的预期中,伦敦金重点知识肯定是那些涉及市场分析的方法,那些方法能帮助投资者一把抓住交易机会,在市场中建立优势。但笔者要说的是,那些方法固然重要,但笔者认为还有更加重要的,那就是控制亏损。控…

大模型增量预训练新技巧:解决灾难性遗忘

大家好,目前不少开源模型在通用领域具有不错的效果,但由于缺乏领域数据,往往在一些垂直领域中表现不理想,这时就需要增量预训练和微调等方法来提高模型的领域能力。 但在领域数据增量预训练或微调时,很容易出现灾难性…

LLM大模型

LLM 学习链接 : 大语言模型 LLM行业背景和市场需求 大模型的涌现能力 大模型核心前沿 大模型应用范式和职业规划

大数据 - Spark系列《四》- Spark分布式运行原理

Spark系列文章: 大数据 - Spark系列《一》- 从Hadoop到Spark:大数据计算引擎的演进-CSDN博客 大数据 - Spark系列《二》- 关于Spark在Idea中的一些常用配置-CSDN博客 大数据 - Spark系列《三》- 加载各种数据源创建RDD-CSDN博客 目录 🍠…

200行C++代码写一个网络调试助手(TCP服务端TCP客户端)

前言 今天分享一个200行C代码写成的QT网络调试助手。 可以先看看效果 。 因为我不喜欢用QT Designer,因此我用的组件都是使用代码布局的,所以需要设计一下布局。 界面是参考的之前写的串口助手,就是把里面的逻辑改了改,因此外观…

关于网络面试题汇总

什么是TCP/IP五层模型?它们的作用是啥?基于TCP/IP实现的应用(层协议)有哪些? TCP/IP五层模型,从上向下分别是: 应用层:应用程序本身,应用层的作用是负责应用程序之间的…

比特币ETF广告战大爆发!

作者:秦晋 贝莱德主动发起广告攻势。 2月1日,据外媒Cryptoslate报道,贝莱德在提交给美国SEC的一份文件中显示,其提出一项在建筑物侧面投影比特币ETF广告计划。 据介绍,广告内容为:「IBIT」信号是一个以迈阿…

IP风险画像在企业网络安全中应用

随着企业数字化的不断深入,网络安全问题日益突显。IP风险画像作为一种综合性的网络安全工具,为企业提供了更全面的风险评估和防范手段。本文将结合一个实际案例,深入探讨IP风险画像在企业网络安全中的成功应用。 案例背景 一家大型金融机构…

VS2019 添加程序包

dotnet add package AlibabaCloud.SDK.Bailian20230601 来提示添加程序包 选择菜单栏 项目----管理NuGet程序包 输入程序包的名称,然后添加即可, 这只是给当前工程添加,并不是给VS添加,所以你打开新工程,需要使用的话…

详解WebRTC rtc::Thread实现

rtc::Thread介绍 rtc::Thread类不仅仅实现了线程这个执行器(比如posix底层调用pthread相关接口创建线程,管理线程等),还包括消息队列(message_queue)的实现,rtc::Thread启动后就作为一个永不停止的event l…

【图论】基环树

基环树其实并不是树,是指有n个点n条边的图,我们知道n个点n-1条边的连通图是树,再加一条边就会形成一个环,所以基环树中一定有一个环,长下面这样: 由基环树可以引申出基环内向树和基环外向树 基环内向树如…

【开源】WordPress一键崩溃宕机插件(整活娱乐)

插件介绍 可一键实现Wordpress崩溃宕机的整活向插件(请勿用于非法途径,仅供整活娱乐)。鼓励关注网站性能的提升,以提供更好的用户体验,提倡为用户提供良好体验和高效速度的原则。 介绍 长期以来,人们都在…

WordPress从入门到精通【安装部署】

初识WordPress WordPress,简称WP,其简称的由来是取英文单词“word”与“press”的首字母 WP中文官网 1WP主站(英文) 官方标称,已有43%的网站在使用WordPress WordPress亮点 WP使用PHP语言开发,兼容性极…

深度学习/自动驾驶数据集大集合(目标检测/图像分割/语义分割/图像分类/)

深度学习和自动驾驶技术的发展离不开高质量的数据集,这些数据集对于训练和验证各种自动驾驶算法和模型起着至关重要的作用。深度学习/自动驾驶数据集大集合是一项汇集了多种场景、多种数据类型的数据资源,旨在为深度学习和自动驾驶领域的研究者和从业者提…

设计模式-行为型模式(上)

行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。 行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为&…

【服务器】RAID(独立磁盘冗余阵列)

RAID(独立磁盘冗余阵列) 一、RAID的介绍二、RAID的分类#2-1 RAID 02-2 RAID 1#2-3 RAID 32-4 RAID 52-5 RAID 62-6 RAID 10(先做镜像,再做条带化)2-7 RAID 01(先做条带,再做镜像)2-8 RAID比较 三、磁盘阵列…

CSDN文章导出工具

源码地址: github:https://github.com/lishuangquan1987/CSDNExportergitee:https://gitee.com/lishuangquan1987/csdnexporter 介绍 最近有CSDN博客导出来的需求,翻看了很多开源工具,都不能用或者不好用,于是决定自己做一个。…

机器学习6-逻辑回归

逻辑回归是机器学习中一种常用于二分类问题的监督学习算法。虽然名字中包含“回归”,但实际上它用于分类任务,特别是对于输出为两个类别的情况。逻辑回归通过使用 logistic 函数将输入映射到一个在0,1范围内的概率值,然后根据这个概率值进行分类。 以下是逻辑回归的基本概念…

线程池,定时器以及阻塞队列(生产者/消费者模型)

💓 博客主页:从零开始的-CodeNinja之路 ⏩ 收录专栏:线程池,定时器以及阻塞队列(生产者/消费者模型) 🎉欢迎大家点赞👍评论📝收藏⭐文章 实现线程池,定时器以及阻塞队列,生产者/消费者模型 线程池线程池…

c++用户管理信息(类指针数组)

用户管理信息--类指针数组 类示意图select类示意图MyIterator示意图VetorCstu示意图ClassStu示意图 项目源代码selectselect.hselect.cpp MyIteratorMyIterator.hMyIterator.cpp VetorCstuVetorCstu.hVetorCstu.cpp ClassStuClassStu.hClassStu.cpp main源码 总结---数组管理指…