C语言可执行程序到底怎样生成?

news2024/11/18 20:02:50

目录

程序的翻译环境

NO1.VS编译器工具

NO2.VS链接器工具

NO3.链接库是什么?

编译

预处理

编译

汇编

链接 

程序的执行环境


C语言的程序到底是怎样生成的呢?又怎样去执行呢?我们来探索。本篇是讲解编译环境。

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

test.c----->test.i------->test.s----->test.obj----->test.exe

程序的翻译环境

程序的翻译环境同时又分为两个阶段 编译链接  

  • 组成一个程序的每个源文件通过编译过程分别转换成目标代码(object code)。
  • 每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序
  • 链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。 
  • 在windows环境下,生成相应的目标文件test.obj
  • 在Linux环境下,生成的目标文件是test.o
  •  test.c源文件---------->test.obj目标文件+链接库------------>test.exe可执行程序 

理解图: 

以我们的VS编译器为例子。编译和链接依赖的是什么工具呢? 

NO1.VS编译器工具

  • 那在我们的VS2022集成开发环境下,VS依赖就是cl.exe这个工具去实现编译这项功能。
  • 在windows环境下,生成相应的目标文件test.obj
  • 在Linux环境下,生成的目标文件是test.o

NO2.VS链接器工具

  • VS2022集成开发环境下,VS依赖就是cl.exe这个工具去实现链接这项功能。
  • 在不同的编译环境下,标准库中的实现肯定是有差异的。

NO3.链接库是什么?

#include<stdio.h>
int main()
{
	printf("hehe\n");
	return 0;
}
  • 例如 像上面的#include<stdio.> printf库函数 我们就直接使用,是因为放在了链接库中直接供给我们使用。标准库中 提供的 现成的库函数 都是以链接库的形式给我们提供的。

编译

其实编译本身也分为几个阶段:预编译(预处理)  编译 汇编 这三个阶段。我们接下来分别探索一下这三个阶段分别干了什么事情。我们整个过程都在 : Linux环境下,使用gcc编译器去验证整个过程。test.c------->test.i--------->test.s----->test.o(test.obj)

具体要用到的指令:

  1. 预处理 选项 gcc -E test.c -o test.i 预处理完成之后就停下来,预处理之后产生的结果都放在test.i文件中。
  2. 编译 选项 gcc -S test.c 编译完成之后就停下来,结果保存在test.s中。
  3. 汇编 gcc -c test.c 汇编完成之后就停下来,结果保存在test.o中。 

预处理


我们想要展示一个预处理的效果,那我们希望预处理之后这个代码就不会往后继续执行了。这里我们要用到一个gcc的指令: -E  test.c  / test.c -E预处理之后test.c代码不会往后继续执行

在我们VS验证之后我们发现我们预处理的文件名为test.i 所以这里在Linux环境下,我们使用gcc指令:-o test.i  (test.c预处理完之后的文件命名为test.i,如果没有指定就直接打印在屏幕上了)

 

在观察了test.ctest.i两个文件差异我们发现预处理对源代码做了一些文本操作处理的。 

  • 注释的替换(删除)。注释被替换成一个空格
  • 头文件的包含#include< >
  • #define符号的替换
  • #include和#define这种都是 预处理指令所有的预处理指令都在预处理阶段处理的。

在我们的下篇博客我们也会详细去讲到预处理这个阶段的知识点。 

注释的删除 

头文件的包含 

编译


来到我们的编译阶段,我们想要展示一个编译的效果,那我们希望编译之后这个代码就不会往后继续执行了。这里我们要用到一个gcc的指令: -S  test.i  / test.i -S编译之后test.i代码不会往后继续执行

同时我们也可以使用gcc指令:-o test.s  (test.i编译完之后的文件命名为test.s,如果没有指定也会生成test.s

我们发现test.s里面放置的都是汇编代码。 其实编译的过程就是:把C语言代码翻译成了汇编代码。这个过程是非常非常复杂的。简单来说,编译这个过程包含:

  • 语法分析
  • 词法分析
  • 语义分析
  • 符号汇总

汇编


到这里,汇编语言依旧不能被我们计算机读懂,汇编语言必须经过汇编器转化成二进制指令,才能被计算机读懂。

我们想要展示一个汇编的效果,那我们希望汇编之后这个代码就不会往后继续执行了。这里我们要用到一个gcc的指令: -c  test.s  / test.s -c汇编之后test.s代码不会往后执行

同时我们也可以使用gcc指令:-o test.o(test.obj)  (test.s汇编完之后的文件命名为test.o,如果没有指定也会生成test.o

我们发现test.o里面放置的都是二进制信息代码。 其实汇编的过程就是:把汇编代码翻译成二进制指令(目标文件)。到此为止,计算机看得懂了。

  • 生成符号表

链接 

现在我们的目标文件test.obj 在gcc指令下:gcc test.o(test.obj) -o test.c(test.exe)  (test.o链接完之后的文件命名为test.c,如果没有指定也会生成test.c(其实就是test.exe可执行程序

 

  • 链接目标文件obj和链接库生成可执行程序(二进制程序)
  • 合并段表
  • 合并符号表和符号表的重新定位

程序的执行环境

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

【推荐书籍】《程序员的自我修养》 

【VIM学习资料】

简明 Vim 练级攻略 | 酷 壳 - CoolShell

【给程序员的VIM速查卡】

https://coolshell.cn/articles/5479.html

✔✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正!

希望大家都有好好学习,好好敲代码。好好生活哦

代码------→【gitee:唐棣棣 (TSQXG) - Gitee.com】

联系------→【邮箱:2784139418@qq.com】

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

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

相关文章

如何避免osg绘制场景时因Z冲突导致绘制重影或不正常

目录 1. 问题的提出 2. Z冲突&#xff08;z-fighting&#xff09;简介 2.1. Z冲突&#xff08;z-fighting&#xff09;产生的原因 2.2. 如何消除Z冲突&#xff08;z-fighting&#xff09; 3. 代码实现 1. 问题的提出 今天绘制了一个棋盘格&#xff0c;鼠标在棋盘格上单击…

亲测防止google colab自动disconnect断连GPU

最近小虎在用colab跑diffusion的模型&#xff0c;但是运行的时候一直断连&#xff0c;就算充了会员也依然如此。 坏境 win11 chrome 解决方法 用Ctrl shift i打开console&#xff0c;输入 function ClickConnect() {console.log("Working");document.querySe…

倒计时 1 天|KCD 2023 杭州站

距离「KCD 2023 杭州站」开始只有 1 天啦 大家快点预约到现场哦&#xff5e; KCD 2023 活动介绍 HANGZHOU 关于 KCD Kubernetes Community Days&#xff08;KCD&#xff09;由云原生计算基金会&#xff08;CNCF&#xff09;发起&#xff0c;由全球各国当地的 CNCF 大使、CNCF 员…

STM32串口

前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 目前已经学习了GPIO的输入输出&#xff0c;但是没有完整的显示信息&#xff0c;最便宜的显示就是串口。 000 -111 AVR单片机 已经学会过了&#xff0c; 提示&#xff1a;以下是本篇文章正文内容&#x…

金蝶与电商集成如何调用奇门接口

电商领域的发展日新月异&#xff0c;为了实现企业的数字化转型&#xff0c;金蝶云等财务系统与电商平台的集成变得愈发关键。在本文中&#xff0c;我们将深入探讨奇门接口的应用&#xff0c;以及为什么它对于金蝶与电商集成如此重要。同时&#xff0c;我们将介绍如何借助轻易云…

【c➡️c++】打开c++学习之门2——内联函数-auto-空值(nullptr)

目录 &#x1f36d;内联函数 &#x1f576;️概念 &#x1f576;️特性&#xff1a; &#x1f449;auto关键字(C11) ➡️类型别名思考 ➡️ auto简介 ➡️auto的使用细则 ➡️auto不能推导的场景 &#x1f308;基于范围的for循环(C11) &#x1f6a9;范围for的语法 &…

基于java(ssm)水果销售管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

开箱即用的Appimage是什么以及如何建立快捷方式

1 引言 在使用Linux系统过程中&#xff0c;初学者会遇到无穷多的问题&#xff0c;包括软件的安装问题。 ubuntu的deb,centos的rpm, 当然以及需要解压的tar.gz等等。有一种开箱即用的软件安装类型&#xff0c;格式为Appimage。 AppImage 的官方网站是 AppImage | Linux apps tha…

Mysql中的RR 隔离级别,到底有没有解决幻读问题

Mysql 中的 RR 事务隔离级别&#xff0c;在特定的情况下会出现幻读的问题。所谓的幻读&#xff0c;表示在同一个事务中的两次相同条件的查询得到的数据条数不一样。 在 RR 级别下&#xff0c;什么情况下会出现幻读 这样一种情况&#xff0c;在事务 1 里面通过 update 语句触发当…

React基础: 项目创建 JSX 基础语法 React基础的组件使用 useState状态 基础样式控制

01 React 文章目录 01 React一、React是什么1、React的优势 二、React开发环境搭建1、创建项目2、运行项目3、项目的目录结构 三、JSX基础1、什么是 JSX代码示例&#xff1a; 2、JSX使用场景2.1代码示例&#xff1a; 3、JSX中实现列表渲染4、JSX - 实现基本的条件渲染5、JSX - …

Cmake用户交互指南

文章目录 一. 介绍1. 命令行cmake工具2. cmake gui工具 二. 生成构建系统1. 命令行环境2. 命令行-G选项3. 在cmake gui中选择生成器 三. 设置生成变量1. 在命令行上设置变量2. 使用cmake gui设置变量3. CMake缓存 四. 预设1. 在命令行上使用预设2. 在cmake gui中使用预设 五. 调…

【五:(mock数据)springboot+mock集成swaggerConfig】

目录 1、springboot 的Demo2、实例类3、服务类 get请求方法4、服务类的post请求方法5、swaggerConfig 接口文档生成配置依赖 SpringBootApplication ComponentScan("com.course") public class Application {public static void main(String[] args) {SpringApplicat…

【TensorFlow1.X】系列学习笔记【基础一】

【TensorFlow1.X】系列学习笔记【基础一】 大量经典论文的算法均采用 TF 1.x 实现, 为了阅读方便, 同时加深对实现细节的理解, 需要 TF 1.x 的知识 文章目录 【TensorFlow1.X】系列学习笔记【基础一】前言线性回归非线性回归逻辑回归总结 前言 本篇博主将用最简洁的代码由浅入…

AD20原理图库的制作

1、打开“51单片机最小系统”的工程文件。 2、创建原理图库文件&#xff1a;单击“文件”菜单&#xff0c;选择“新的”选项中的“库”选项&#xff0c;再选择“原理图库”&#xff0c;进入原理图库元件的编辑界面。 3、保存原理图库文件&#xff1a;选择“文件”菜单&#xff…

antd vue 组件 使用下拉框的层级来显示后面的输入框

效果图&#xff1a; 代码&#xff1a; HTML: <dir><a-row><a-col :span"4"><a-form-model-item label"审批层级" ><a-selectplaceholder"请选择审批层级"v-model"form.PlatformPurchaseApproveLevel"cha…

安达发|人工智能在APS高级计划与排程中的应用

随着人工智能&#xff08;AI&#xff09;技术的发展&#xff0c;其在生产计划与排程&#xff08;APS&#xff09;领域的应用也日益广泛。APS是一种复杂的系统工程&#xff0c;它需要处理大量的数据&#xff0c;包括需求预测、资源优化、路径规划等。AI技术的应用可以帮助企业更…

身份证读卡器ubuntu虚拟机实现RK3399 Arm Linux开发板交叉编译libdonsee.so找不到libusb解决办法

昨天一个客户要在RK3399 Linux开发板上面使用身份证读卡器&#xff0c;由于没有客户的开发板&#xff0c;故只能用本机ubuntu虚拟机来交叉编译&#xff0c;用客户发过来的交叉编译工具&#xff0c;已经编译好libusb然后编译libdonsee.so的时候提示找不到libusb&#xff0c;报错…

语音芯片KT142C两种音频输出方式PWM和DAC的区别

目录 语音芯片KT142C两种音频输出方式PWM和DAC的区别 一般的语音芯片&#xff0c;输出方式&#xff0c;无外乎两种&#xff0c;即dac输出&#xff0c;或者PWM输出 其中dac的输出&#xff0c;一般应用场景都是外挂功放芯片&#xff0c;实现声音的放大&#xff0c;比如常用的音箱…

csapp-Machine-Level Representation of Program-review

Machine-Level Representation of Program收获和思考 Basics Machine-Level Programming可以看成是机器执行对于上层代码的一种翻译&#xff0c;即硬件是如何通过一个个的指令去解释每一行代码&#xff0c;然后操纵各种硬件执行出对应的结果。 Machine-Level Programming有2种…

Jprofiler V14中文使用文档

JProfiler介绍 什么是JProfiler? JProfiler是一个用于分析运行JVM内部情况的专业工具。 在开发中你可以使用它,用于质量保证,也可以解决你的生产系统遇到的问题。 JProfiler处理四个主要问题: 方法调用 这通常被称为"CPU分析"。方法调用可以通过不同的方式进行测…