C语言程序环境剖析——探究从.c到.exe之路

news2025/5/26 7:23:03

程序环境

    • 1.程序的翻译环境和执行环境
    • 2. 详解编译+ 链接
      • 2.1 翻译环境
      • 2.2 编译的三部分
        • 预编译
        • 编译
        • 汇编
      • 2.3链接
    • 3.运行环境

1.程序的翻译环境和执行环境

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

  1. 翻译环境,在这个环境中源代码被转换成可执行的机器指令。
    (例如:vs2022这个集成开发环境就包括翻译环境)
  2. 执行环境, 它用于实际执行代码

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 后缀文件性质相同。
在这里插入图片描述
汇编过程的进行大致有以下两步:

  1. 形成符号表

在编译过程中进行了符号汇总,而形成符号表简单来说就是将这些符号与地址配对,符号表 = 符号+地址
例如上面那个例子,两个文件的符号表就可以如此表示:
(地址是博主随便设的(doge))
test.c的符号表

符号地址
g_val0x010
Add0x783
main0x666

add.c的符号表

符号地址
Add0x200
g_val0x300
  1. 汇编指令-> 二进制指令 ------->test.o和add.o

2.3链接

链接部分主要执行两个操作:

  1. 合并段表
  2. 符号表的合并和符号表的重定位

这里为了解释合并段表,我们进行一定的扩展:

在linux环境下,生成的test.o和可执行程序都是elf格式的文件,而elf格式的文件时分段式的结构,每个段放置不同功能的数据,如图:
在这里插入图片描述
也就是说,这里段表的合并就是把多个.o文件中相同功能的段合并在一起。

而符号表的合并和重定位就是将相同的符号合并,并且替换掉无效的地址。

就拿刚才的例子来说,test.c 中的g_val 和Add符号是用extern外部引入的,需要在其他的文件才能找到其定义,也就是说,此时test 文件的符号表中这两个的地址是无效的,真正有效的地址在add.c中,因此需要进行合并。

上诉代码合并之后的符号表如下:

符号地址
g_val0x300
Add0x200
main0x666

以上就是从.c文件到.exe 文件的大体过程啦,当然其实编译的过程还有很多细节,如果有机会,之后博主会继续补充的嘿嘿!


3.运行环境

程序的执行过程:

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

以上就是关于程序环境的相关内容了,如果觉得写的不错还请大家多多点赞啊哈哈!

在这里插入图片描述

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

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

相关文章

three.js 基础认识与简单应用

一、前言 1. 什么是three.js&#xff1f;你将它理解成threejs&#xff0c;three表示3D的意思&#xff0c;js表示JavaScript的意思&#xff0c;合起来&#xff0c;three.js就是使用JavaScript来写3D程序的意思。three.js是基于WebGL的一个运行在浏览器上的开源框架&#xff0c;使…

企业级安全软件装机量可能大增

声明 本文是学习大中型政企机构网络安全建设发展趋势研究报告. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 研究背景 大中型政企机构是网络安全保护的重中之重&#xff0c;也是国内网络安全建设投入最大&#xff0c;应用新技术、新产品最多的机构…

云原生系列之使用 prometheus监控MySQL实战

文章目录前言一. 实验环境二. 安装MySQL5.72.1 配置yum源2.2 安装MySQL之前的环境检查2.3 开始使用yum安装2.4 启动MySQL并测试三. 安装MySQL_exporter3.1 MySQL_exporter的介绍3.2 mysql_exporter的安装3.3 设置MySQL账户&#xff0c;用于数据收集3.4 启动mysql_exporter3.5 配…

2023年信息系统项目管理师,需要哪些备考资料?

其实考前心态是相当重要的&#xff0c;你需要战胜的一直是你自己。你首先要明确自己考试必胜的决心&#xff0c;树立好的备考心态&#xff0c;学习只要用对了方法&#xff0c;考试通过的几率还是挺高的。备考心得&#xff1a;我自己备考了3个月的时间通过了&#xff0c;分享一套…

Linux多线程---生产者消费者模型和线程池

目录 生产者消费者模型 条件变量 接口 实现基于阻塞队列的cp模型 POSIX信号量 信号量的PV操作 接口&#xff1a; 初始化信号量&#xff1a; 销毁信号量 等待信号量 发布信号量 基于环形队列的生产者消费者模型 线程池 应用场景&#xff1a; 如何实现&#xff1f; …

DHCP中继及配置

为什么需要DHCP Relay&#xff1f;产生背景解决方案DHCP Relay工作原理DHCP Relay配置实现产生背景 随着网络规模的扩大&#xff0c;网络中就会出现用户处于不同网段的情况。 这个时候客户A和客户B要请求IP地址时&#xff0c;首先会发送DHCP Discover广播包&#xff0c;这个广…

一本关于ChatGPT的书《ChatGPT 革命:了解大型语言模型的力量》免费下载

下载地址&#xff1a;https://download.csdn.net/download/winniezhang/87431530 这本书有什么不同&#xff1a; 1、从书名&#xff0c;到大纲&#xff0c;到内容&#xff0c;基本都来自ChatGPT的自述&#xff0c;本人只是负责编辑。 2、整个成书过程只用了2小时不到。 3、…

【排序算法】堆排序(Heap Sort)

堆排序是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构&#xff0c;并同时满足堆积的性质&#xff1a;即子结点的键值或索引总是小于&#xff08;或者大于&#xff09;它的父节点。堆排序介绍学习堆排序之前&#xff0c;有必要了解堆&#xff01;若…

【HTML】HTML 表格 ② ( 表头单元格标签 | 表格标题标签 )

文章目录一、表头单元格标签二、表格标题标签一、表头单元格标签 表头单元格 可以在表格中 用作第一排 作为表格 的 表头 使用 , 表头单元格 中的 文本设置 可以与 普通单元格 中的文本设置 不同 ; 表头单元格 中的 文本 会 居中 , 并且 加粗 显示 ; 表头单元格 标签 如下 : &…

2023彻底解决Typora使用iPic微博图床失效问题

一、问题描述用Typora搭配iPic图床使用&#xff0c;最近csdn图片显示不出来用浏览器打开图片显示403&#xff0c;这里原因是微博图床出问题了导致的而使用iPic其他图床则需要一直付费&#xff0c;那有没有一劳永逸的解决所有问题呢&#xff1f;二、旧图恢复首先怎么找回旧图&am…

数字信号处理-第一章 离散时间信号与系统

1.1 离散时间信号——序列 1.1.1 序列 离散时间信号只在离散时间上给出函数值&#xff0c;是时间上不连续的序列。一 般 &#xff0c;离散时间的间隔是均匀的&#xff0c;以TTT表示&#xff0c;故用 x(nT)x(nT)x(nT)表示此离散时间信号在nTnTnT点上的值&#xff0c;nnn为整数…

省钱的年轻人,钱包被折扣店钻了空子

【潮汐商业评论/原创】过年期间&#xff0c;除了商场超市&#xff0c;小区附近的折扣店成了Amy经常光顾的对象。用Amy的话来说&#xff0c;“跟附近超市比价格&#xff0c;跟大卖场比距离&#xff0c;综合下来折扣店就是我随时购物的不二选择。”从Amy的话里&#xff0c;我们可…

LeetCode-101. 对称二叉树

目录题目分析递归法题目来源 101. 对称二叉树 题目分析 首先想清楚&#xff0c;判断对称二叉树要比较的是哪两个节点&#xff0c;要比较的可不是左右节点&#xff01; 对于二叉树是否对称&#xff0c;要比较的是根节点的左子树与右子树是不是相互翻转的&#xff0c;理解这一…

如何在 Mac 上将 PDF 转换为 Word [6 种免费方法]

我们出于各种原因使用 PDF。我们可以将它们用于学校作业&#xff0c;以打印出谱&#xff0c;或离线阅读文章。我们经常想弄清楚如何在 Mac 上将 Word 文档另存为 PDF。但是&#xff0c;如果我们需要对 PDF 进行更改怎么办&#xff1f; 对 PDF 进行更改通常无法在 PDF 本身上完…

Vue3通透教程【二】更高效的构建工具—Vite

文章目录&#x1f31f; 写在前面&#x1f31f; webpack&#x1f31f; Vite是什么&#xff1f;&#x1f31f; 使用Vite创建项目&#x1f31f; 写在最后&#x1f31f; 写在前面 专栏介绍&#xff1a; 凉哥作为 Vue 的忠实 粉丝输出过大量的 Vue 文章&#xff0c;应粉丝要求开始更…

【成为架构师课程系列】架构师的核心能力地图

目录 架构师核心能力总结 #综合技术能力分层总结 #数据结构和算法知识图谱总结 #Java工程师【核心基础】知识图谱总结

全栈开发工程师面试题五-Eureka

1.服务的提供者和服务的消费者&#xff08;服务的调用关系&#xff09; 服务的提供者&#xff1a;在一次服务中被其他服务调用的服务(提供接口给其他服务) 服务的消费者&#xff1a;一次业务中调用其他服务的服务&#xff08;调用其它微服务提供的接口&#xff09; 服务的提供者…

Koa2-创建、中间件、连接数据库、处理请求、日志

文章目录安装配置koa2配置nodemon,热更新我们的项目中间件什么是中间件&#x1f47b;洋葱模型路由中间件连接数据库 - mysql后端允许跨域处理请求getpostputdelete后续会继续更新安装配置koa2 &#x1f47b;安装 koa2 npm i koa2 -s&#x1f47b;在package.json 配置,当然是在…

如何在QEMU社区提Bug

当在编译及使用QEMU的过程中发现问题又不能自行解决时&#xff0c;可以去QEMU官网提Bug。本文以笔者实际遇到的问题为例&#xff0c;讲解提交QEMU Bug的完整过程。 1. 访问QEMU主页 QEMU官网主页地址为&#xff1a;https://www.qemu.org/ 页面如下&#xff1a; 2. 跳转至CON…

RK3566 多Mipi屏的兼容

需求:项目需求需要同一个固件兼容两款不同IC的mipi屏。以便有一个IC停产之后使用不受影响。由于是同一个模组厂商,所以设计初就要求硬件接口一样或者兼容。 方法:一开始的想法很简单和网上以及同行提供的方法一样在uboot阶段去读屏的ID,然后再把对应屏ID放到cmdline里面去传…