C语言程序环境剖析——探究从.c到.exe之路
程序环境
- 1.程序的翻译环境和执行环境
- 2. 详解编译+ 链接
- 2.1 翻译环境
- 2.2 编译的三部分
- 预编译
- 编译
- 汇编
- 2.3链接
- 3.运行环境
1.程序的翻译环境和执行环境
在ANSI C的任何一种实现中,都存在两个不同的环境。
- 翻译环境,在这个环境中源代码被转换成可执行的机器指令。
(例如:vs2022这个集成开发环境就包括翻译环境)- 执行环境, 它用于实际执行代码
2. 详解编译+ 链接
一个.c文件想要编程一个可执行程序,需要经过编译和链接两步, 而编译又可细分为预编译,编译和汇编三过程,如图:
2.1 翻译环境
一个项目可能是由很多个.c文件共同构成的,每个.c文件需要分别进行编译产生.obj
后缀的目标文件(windows环境)
在linux环境下是
.o
为后缀
接着在链接器的作用下将所有目标文件结合在一起进行最后产生了可执行程序。
- 组成一个程序的每个源文件单独通过编译过程分别转换成目标代码(object code)
- 每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序。
- 链接器同时会引入标准C函数库中任何被程序引用到的函数,而且它可以搜索程序员个人的程序库,将其所需要的函数也链接到程序中。
2.2 编译的三部分
下面,我们就以一个例子来为大家简单的解释一下每个步骤都在干什么。
注:以下例子只是用来演示c语言编译各个阶段的特点,无实际意义
test.c
#include<stdio.h>
#include "add.c"
//这是注释
#define M 100
extern int g_val;
extern int Add(int x, int y);
int main()
{//开始struct s k;int b = 10;int c = Add(M,b);printf("%d", c);return 0;//结束
}
add.c
int Add(int x, int y)
{return x + y;
}struct s
{int a;char c;
};int g_val = 100;
预编译
在预编译过程中,会进行的操作有#include
头文件的包含以及#define
宏的替换(预处理指令)还有注释的删除,总的来说,就是对代码文本进行改进。
我们用gcc编译器来编译代码,通过指令使其停在预处理结束之后的阶段,由此来观看代码文本的变化。
在终端输入: gcc -E test.c -o test.i
即可生成预处理之后的文件,然后我们看看文件中的内容,如图:
编译
编译过程主要将进行语法分析,词法分析,语义分析以及符号汇总四个内容,同样,我们可以通过命令的方式得到编译后的文件。
这里简单讲解一下符号汇总,其实就是把函数名和全局变量之类的汇总起来,便于下一步作用。
命令:gcc -S test.c
,然后我们看一下文件内容。
我们可以看到,其实经过编译之后,就是把我们的c语言代码转换为汇编代码。
汇编
接下来就是编译的最后一步,汇编了,通过这一步之后,我们写的c程序就完全转换成了目标文件(object code),由于目标文件是由二进制指令构成,所以我们是没办法看懂的,但是依旧可以通过指令的方式得到汇编后生成的文件。
指令: gcc -C test.c
通过这一指令,将生成test.o的文件,其和我们用vs编译生成的.obj 后缀文件性质相同。
汇编过程的进行大致有以下两步:
- 形成符号表
在编译过程中进行了符号汇总,而形成符号表简单来说就是将这些符号与地址配对,符号表 = 符号+地址
例如上面那个例子,两个文件的符号表就可以如此表示:
(地址是博主随便设的(doge))
test.c的符号表
符号 地址 g_val 0x010 Add 0x783 main 0x666 add.c的符号表
符号 地址 Add 0x200 g_val 0x300
- 汇编指令-> 二进制指令 ------->test.o和add.o
2.3链接
链接部分主要执行两个操作:
- 合并段表
- 符号表的合并和符号表的重定位
这里为了解释合并段表,我们进行一定的扩展:
在linux环境下,生成的test.o和可执行程序都是
elf
格式的文件,而elf格式的文件时分段式的结构,每个段放置不同功能的数据,如图:
也就是说,这里段表的合并就是把多个.o文件中相同功能的段合并在一起。
而符号表的合并和重定位就是将相同的符号合并,并且替换掉无效的地址。
就拿刚才的例子来说,test.c 中的g_val 和Add符号是用extern
外部引入的,需要在其他的文件才能找到其定义,也就是说,此时test 文件的符号表中这两个的地址是无效的,真正有效的地址在add.c中,因此需要进行合并。
上诉代码合并之后的符号表如下:
符号 | 地址 |
---|---|
g_val | 0x300 |
Add | 0x200 |
main | 0x666 |
以上就是从.c文件到.exe 文件的大体过程啦,当然其实编译的过程还有很多细节,如果有机会,之后博主会继续补充的嘿嘿!
3.运行环境
程序的执行过程:
- 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序 的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
- 程序的执行便开始。接着便调用main函数。
- 开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回 地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
- 终止程序。正常终止main函数;也有可能是意外终止。
以上就是关于程序环境的相关内容了,如果觉得写的不错还请大家多多点赞啊哈哈!
相关文章:
C语言程序环境剖析——探究从.c到.exe之路
程序环境1.程序的翻译环境和执行环境2. 详解编译 链接2.1 翻译环境2.2 编译的三部分预编译编译汇编2.3链接3.运行环境1.程序的翻译环境和执行环境 在ANSI C的任何一种实现中,都存在两个不同的环境。 翻译环境,在这个环境中源代码被转换成可执行的机器指…...
【软件测试】8年资深测试总结出的测试学习经验,从入门到测试开发......
目录:导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜)前言 测试圈子里有一句话…...
【博学谷学习记录】超强总结,用心分享|Spark的RDD算子分类
概念 RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,代表一个不可变、可分区、里面的元素可并行计算的集合,它是一种抽象的数据模型,本身并不存储数据,仅…...
云原生系列之使用 prometheus监控远程主机实战
文章目录前言一. 实验环境二. 安装node_exporter2.1 node_exporter的介绍2.2 node_exporter的安装三. 在prometheus服务端配置监控远程主机3.1 在server端配置拉取node的信息3.2 重启prometheus3.3 通过浏览器查看prometheus总结前言 大家好,又见面了,我…...
2023年地方两会政府工作报告汇总(各省市23年重点工作)
新年伊始,全国各地两会密集召开,各省、市、自治区2023年政府工作报告相继出炉,各地经济增长预期目标均已明确。相较于2022年,多地经济增长目标放缓,经济不断向“高质量”发展优化转型。今年是二十大后的开局之年&#…...
第一章 企业管理概论
目录 一、企业及其形式 二、企业管理概述 三、企业管理理论与实践的产生与发展 四、网络时代的企业环境 五、网络时代企业管理的变革 一、企业及其形式 1、企业的概念 企业以市场为导向,以价值增值作为经济活动的目的; 企业是从事商品生产和流通的…...
独立图片服务器有什么突出之处
服务器是网络中非常重要的设施,承载着不同流量的访问,这就要求服务器具有快速的吞吐量、高稳定性和高可靠性。独立图片服务器作为独立服务器的衍生品,在数据利用方面的应用可以为企业在数据处理和分析方面带来一场革命。本文就将介绍独立图片…...
Linux驱动开发基础__mmap
目录 1 引入 2 内存映射现象与数据结构 3 ARM 架构内存映射简介 3.1 一级页表映射过程 3.2 二级页表映射过程 4 怎么给 APP 新建一块内存映射 4.1 mmap 调用过程 编辑4.2 cache 和 buffer 4.3 驱动程序要做的事 5 编程 5.1 app编程 5.2 hello_drv_test…...
若依框架---为什么把添加和更新分成两个接口
👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者 📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 Ǵ…...
图论算法:Floyd算法
文章目录Floyd算法例题:灾后重建Floyd算法 Floyd算法用于求图中任意两点之间的最短路径,该算法主要运用了动态规划的思想。 思考: 给你几个点与边,可以组成一张图,那么如何求得任意两点之间的最短路径呢?…...
回顾 | .NET MAUI 跨平台应用开发 - 用 .NET MAUI 开发一个无人机应用(下)
点击蓝字关注我们编辑:Alan Wang排版:Rani Sun微软 Reactor 为帮助广开发者,技术爱好者,更好的学习 .NET Core, C#, Python,数据科学,机器学习,AI,区块链, IoT 等技术,将…...
部署有多个仓库的svn服务
centos7自带svn服务,现需要创建多个仓库,并实现用户读写功能 创建svn版本库 mkdir /home/svn mkdir /home/svn/confmkdir /home/svn/yk1 mkdir /home/svn/yk2 svnadmin create /home/svn/yk1 svnadmin create /home/svn/yk2 进入版本库yk1的配置文件路…...
Mapper文件注入问题
Mapper文件注入问题UserMapper that could not be found.原因分析解决方案程序正常运行,但是注入类爆红问题原因分析解决方法UserMapper’ that could not be found. 原因分析 撰写了mapper文件,但是没有注入spring容器 解决方案 添加mybatis.mapper-…...
基于微信小程序的国产动漫论坛小程序
文末联系获取源码 开发语言:Java 框架:ssm JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7/8.0 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven3.3.9 浏览器…...
常用限流算法
简单时间窗口 算法逻辑:设置周期时间内的最大并发量问题:在周期尾端进去阈值并发后,进入下一周期时,又进入阈值并发量,则会出现瞬时并发量是阈值的2倍。 滑动时间窗口(优化) 算法逻辑…...
前端面经详解
目录 css 盒子充满屏幕 A.给div设置定位 B.设置html,body的宽高 C.相对当前屏幕高度(强烈推荐) 三列布局:左右固定,中间自适应 flex布局(强烈推荐) grid布局 magin负值法 自身浮动 绝对定位 圣…...
网页CAD开发快速入门
演示说明 提示:目前提供两种在网页中浏览编辑CAD图纸方案,详细说明见:MxDraw帮助 网页中打开CAD最简步骤: 第一步: 安装插件运行环境,下载安装(可能需要退杀毒软件):https://demo.mxdraw3d.com:3562/MxDrawx86Setup…...
C#开发的OpenRA的mod.yaml文件
C#开发的OpenRA的mod.yaml文件 在OpenRA游戏里,会看到这样一段代码: Manifest LoadMod(string id, string path){IReadOnlyPackage package = null;try{if (!Directory.Exists(path)){Log.Write("debug", path + " is not a valid mod package");return …...
【ESP32+freeRTOS学习笔记-(七)中断管理】
目录1、概述2、在ISR中使用FreeRTOS中专用的API2.1 独立的用于ISR中的API2.2 关于xHigherPriorityTaskWoken 参数的初步理解3、延迟中断处理的方法-将中断中的处理推迟到任务中去4 方法一:用二进制信号量来同步ISR与”延时处理的任务“4.1 二进制信号量4.2 函数用法…...
【总结】1591- 从入门到精通:使用 TypeScript 开发超强的 CLI 工具
作为一名开发者,掌握 CLI 工具的开发能力是非常重要的。本文将指导你如何使用 TypeScript 和 CAC 库开发出功能强大的 CLI 工具。快速入门首先,需要先安装 Node.js 和 npm(Node Package Manager),然后在项目目录中创建…...
【Java】int和Integer的区别?为什么有包装类?
int和Integer的区别?为什么有包装类? java是一种强类型的语言,所以所有的属性都必须要有一个数据类型。 PS:java10有了局部变量类型推导,可以使用var来代替某个具体的数据类型,但是在字节码阶段࿰…...
【LeetCode】石子游戏 IV [H](动态规划)
1510. 石子游戏 IV - 力扣(LeetCode) 一、题目 Alice 和 Bob 两个人轮流玩一个游戏,Alice 先手。 一开始,有 n 个石子堆在一起。每个人轮流操作,正在操作的玩家可以从石子堆里拿走 任意 非零 平方数 个石子。 如果石…...
修改Vue项目运行的IP和端口
前言 我们在使用VsCode启动Vue项目的时候,我发现:默认的端口号好像和tomcat一样,默认都是8080,如果8080被占用了,就会使用8081,8082这样的方式以此类推。 那么,我们是否可以像后端一样,通过修改…...
【C++提高编程】map/ multimap 容器详解(附测试用例与结果图)
目录1. map/ multimap容器1.1 map基本概念1.2 map构造和赋值1.3 map大小和交换1.4 map插入和删除1.5 map查找和统计1.6 map容器排序1.7 案例-员工分组1.7.1 案例描述1.7.2 实现步骤1. map/ multimap容器 1.1 map基本概念 简介: map中所有元素都是pairpair中第一个…...
laravel操作redis和缓存操作
一:操作redis1:redis拓展安装composer require predis/predis或者你也可以通过 PECL 安装 PhpRedis PHP 扩展,安装方法比较复杂,个人不推荐2:配置redis在config/database.php文件中配置redis(1):单个redis配置redis > [client …...
目标检测论文阅读:GaFPN算法笔记
标题:Construct Effective Geometry Aware Feature Pyramid Network for Multi-Scale Object Detection 会议:AAAI2022 论文地址:https://ojs.aaai.org/index.php/AAAI/article/view/19932 文章目录Abstract1. Introduction2. Related Work2.…...
【转】Generative Pretrained Transformer
原文链接:https://www.cnblogs.com/yifanrensheng/p/13167796.html一、GPT简介1.1 背景目前大多数深度学习方法依靠大量的人工标注信息,这限制了在很多领域的应用。此外,即使在可获得相当大的监督语料情况下,以无监督学习的方式学…...
day34|343. 整数拆分、96.不同的二叉搜索树
343. 整数拆分 给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k > 2 ),并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 示例 1: 输入: n 2 输出: 1 解释: 2 1 1, 1 1 1。 示例 2: 输入: n 10 输出: 36 解…...
WeNet - 初识
文章目录关于 WeNet快速上手识别训练环境准备训练关于 WeNet Production First and Production Ready End-to-End Speech Recognition Toolkit github: https://github.com/wenet-e2e/wenet官方中文说明:https://github.com/wenet-e2e/wenet/blob/main/README_CN.md…...
为什么各个企业都在创建FAQ、常见问题页面?
常见问题解答页面是您可能已经为您的公司考虑过的东西,作为帮助客户回答有关您的产品和服务的常见问题的一种方式。但是您不知道最好的方法;肯定这只是一个问题清单吗?常见问题解答在整个购买过程中为客户提供支持,并减少客户需要与贵公司的联…...
phpcms仿行业网站/全网推广公司
一、volatile的定义 Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。Java语言 提供了volatile,在某些情况下比锁要更加方便。如果一个字段被声明成volatile,Ja…...
双语 网站 数据怎么做/vue seo 优化方案
写成宏,方便移植#define setbit(x,y) x|(1<//将X的第Y位置1#define clrbit(x,y) x&~(1<方法二:C语言位运算除了可以提高运算效率外,在嵌入式系统的编程中,它的另一个最典型的应用,而且十分广泛地正在被使用着的是位间的…...
网站开发制作公司简介/百度指数是什么
参考:http://www.cnblogs.com/denny402/p/5073427.html转载于:https://www.cnblogs.com/573177885qq/p/5805027.html...
沈阳做网站客户多吗/网址收录入口
defaultExpandAll:autoExpandParent"true":treeData"treeData"select"this.onSelect"/>data () {return {// expandedKeys: [0-0-0, 0-0-1], // 受控展开指定的树节点autoExpandParent: true, // 是否自动展开父节点// checkedKeys: [0-0-0],…...
一般网站是怎么做的/seo综合查询怎么用
在查询了资料后,mysql的begin end 只能使用在流程控制语句,游标,触发器,存储过程中...
网站栏目关键词/超级外链
java中map的取值 博客分类: java基础 mapvaluejava package com.itcast.map; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.junit.Test; public class MapTest { /** * 取得Map里面的值的两种方…...