【C语言】.c源文件从编译到链接生成可执行程序的过程

news2024/11/30 2:41:23

本篇文章目录

  • 1. 过程概览
  • 2. 编译与链接
    • 2.1 预编译/预处理
    • 2.2 编译
    • 2.3 汇编
    • 2.4 链接
  • 3. 执行/运行环境

1. 过程概览

编译到链接是c语言的翻译环境,c语言还有执行环境。

在这里插入图片描述

  1. 组成一个程序的每个源文件通过编译过程分别转换成目标代码(object code);
  2. 每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序;
  3. 链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。

2. 编译与链接

在这里插入图片描述

2.1 预编译/预处理

总的来说都是文本操作,注释被删除替换成一个空格;#define定义的符号也会被删除,其它所有出现这个符号的地方都被替换成所代表的常量;头文件所有函数实现都会包含进来,总共大概一两万行,最后才是自己写的代码。

预编译后会产生一个对应的.i文件,不过要说明的是这个预编译的步骤在vs中可以看到,但后面的步骤基本只能在linux gcc编译器,使用指令一步步看。
在这里插入图片描述
在windows vs中查看预编译后产生的文件:
在这里插入图片描述
选择是然后运行程序,实际程序会编译失败,因为仅仅只进行了预处理这个步骤,不过可以在项目文件下的X64/Debug下看到一个对应的.i文件。
在这里插入图片描述
在这里插入图片描述

在linux下执行预处理选项指令 gcc -E test.c -o test.i(-E代表只进行预处理,-o test.i代表指定输出到这个文件),预处理完成之后就停下来,预处理之后产生的结果都放在test.i文件中。

2.2 编译

在linux下执行编译选项指令 gcc -S test.c,编译完成之后就停下来,结果保存在test.s中。

编译阶段会将c代码转换为汇编代码,汇编大致会经过四个阶段:

  1. 词法分析;
  2. 语法分析;
  3. 语义分析;
  4. 符号汇总。

比如图中左边的这段代码,对应右边编译器一个个符号分析它们分别代表什么。
在这里插入图片描述
语法分析阶段会产生一个语法树:
在这里插入图片描述
语义分析应该是根据语法树进行,我也不是很了解。

符号汇总这个阶段很重要,编译器会将每个.c文件中的全局符号(函数名、全局变量)汇总起来,后面的汇编和链接都会涉及到符号的处理。

2.3 汇编

汇编阶段是将编译阶段产生的.s文件(汇编代码)转成二进制机器码文件。在linux下执行汇编指令 gcc -c test.c,汇编完成之后就停下来,结果保存在test.o中。

在这个阶段会根据前面编译阶段的符号汇总,产生一个符号表,如:
在这里插入图片描述
对于右边申明的Add函数,在符号表中的地址是无效的,后续不会使用这个无效的地址,而是使用左边的地址,符号表在连接阶段会使用。

2.4 链接

链接阶段链接器(linker)会链接所有产生的.obj / .o目标文件,以及链接库生成合并成一个二进制的.exe可执行程序文件,这个阶段会经历合并段表、合并符号表操作。

gcc编译器生成的二进制目标文件和二进制的可执行文件,都是按照elf文件形式组织的,合并段表要做的就是将所有.o文件中相同数据段进行合并在一起;每个文件产生的符号表最后也会合并在一起,符号表中无效的地址会被舍弃,使用有效的地址,因为链接器链接查找函数都是根据符号和地址的匹配关系去找的,不然没法找到;最后生成一个.exe文件。

add.c和test.c的符号表,其中0x0000,无效的地址值会被舍弃:
在这里插入图片描述

如果add.c中没有Add函数,那么符号表中没有对应的函数名Add和地址,那么会连接失败:
在这里插入图片描述

3. 执行/运行环境

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

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

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

相关文章

推荐《一拳超人》

《一拳超人》是ONE原作,村田雄介作画,连载于网络漫画杂志《邻座的Young jump》上的漫画。 [1] 原为ONE在个人网站上连载的练笔之作, [2] 后被喜爱该作的另一漫画家村田雄介在征得ONE同意后重新绘制而成。 简体中文电子版由哔哩哔哩漫画发布…

JavaSE学习值之--认识异常

💕"有效知识的前提是承认知识边界,承认我们对边界那边的一切无可奉告。"💕 作者:Mylvzi 文章主要内容:JavaSE学习值之--认识异常 一.什么是异常? 异常就是程序在运行的时候产生的不正常的行为 …

java_Stream API

文章目录 一、Stream API vs 集合二、Stream 使用的执行流程2.1、创建Stream2.1、中间操作2.1.1. filter2.1.2. limit2.1.3. skip2.1.4. distinct2.1.5. map2.1.6. sorted 一、Stream API vs 集合 Stream API 关注的是多个数据的计算(排序、查找、过滤、映射、遍历…

网络工程师知识点4

51、OSPF的LSA类型 52虚链路:作用 解决区域划分不合理的问题 通过建立虚拟链路来实现一般区域与骨干区域的理论化直连 54、NSSA区域的特点 1、可以学习本区域连接的外部路由 2、不学习其他区域转发进来的外部路由 3、与外部区域通信使用ABR自动产生的默认路…

python:爬取网络小说,看这一篇就够了

说明: 本教程仅供于学习研究使用,请勿用于其他用途。 软件安装: 官网下载visual studio Visual Studio: 面向软件开发人员和 Teams 的 IDE 和代码编辑器 (microsoft.com) 点进网页后下拉找到个人免费版本。点击下载即可。 1:找到…

第六章:TF-A学习

TF-A学习 TF-A初探如何获取系统源码移植过程中遇到的问题和解决方案编译报错:arm-none-linux-gnueabi-gcc: not foundTF-A 源码打补丁 遇到assume -R?[n] TF-A初探 为了保证安全 ARM 推出了 Arm Trusted Firmware 的可信固件,简称 TF-A。它…

windows环境cmake的nmake failed

windows环境cmake异常 问题如下: > cmake ..CMake Error at CMakeLists.txt:4 (PROJECT): Running nmake -?failed with:系统找不到指定的文件。CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage CMake Error: CMAKE_CXX_COMPILER not set, after…

中断机制-interrupt和isInterrupted源码分析、中断协商案例

当前线程的中断标识为true,是不是线程就立刻停止? 答案是不立刻停止,具体来说,当对一个线程,调用interrupt时: 如果线程处于正常活动状态,那么会将该线程的中断标志设置为true,仅此…

【C++】:关键字 命名空间 输入输出 缺省参数 函数重载 引用

【本节目标】 C关键字命名空间C输入&输出缺省参数函数重载引用 C是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式等 熟悉C语言之后,对C学习有一定的帮助,本章节主要目标&#xff…

关于面试以及小白入职后的一些建议

面试的本质 面试的过程是一个互相选择的过程;面试官的诉求是,了解应聘者的个人基本信息、工作态度、专业能力及其他综合能力是否与公司招聘岗位匹配;面试者的诉求是,拿下招聘岗位offer,获得工作报酬; 面试…

【go学习笔记】Go errors 最佳实践

文章目录 一、Error Type1. Sentinel Error(预定义Error字符串错误值)1.1 缺点 2. Error types(错误类型)2.1 缺点 3. Opaque errors(不透明错误)3.1 Assert errors for behaviour, not type 二、Handling …

详解RocketMQ消息存储原理

本文基于RocketMQ 4.6.0进行源码分析 一. 存储概要设计 RocketMQ存储的文件主要包括CommitLog文件、ConsumeQueue文件、Index文件。RocketMQ将所有topic的消息存储在同一个文件中,确保消息发送时按顺序写文件,尽最大的能力确保消息发送的高性能与高吞吐…

SpringBoot实战(二十五)集成 Shiro

目录 一、Shiro 简介1.1 Shiro 定义1.2 Shiro 核心组件1.3 Shiro 认证过程 二、SpringBoot集成2.1 集成思路2.2 Maven依赖2.3 自定义 Realm2.4 Shiro 配置类2.5 静态资源映射2.6 AuthController2.7 User 实体2.8 用户接口类2.9 用户接口实现类2.10 OrderController(…

手把手教你使用Python从零开始搭建感知器

大家好,今天本文将展示如何从零开始实现神经网络的最基本要素(感知器),以及人工智能的基本模块背后的数学原理。 虽然人工智能和机器学习等术语已经成为流行词汇,每天都会听到或谈论这些概念,但它们背后的…

软件开发介绍

一、软件开发整体介绍 作为一名软件开发工程师,我们需要了解在软件开发过程中的开发流程,以及软件开发过程中涉及到的岗位角色,角色的分工、职责,并了解软件开发中涉及到的三种软件环境。 1.1 软件开发流程 第一阶段&#xff1a…

MQTT解读【全网最易懂】

目录 前言 一、MQTT相比于TCP长连接的优势 1、协议更标准 2、MQTT协议制定好了很多利于物联网的功能 3、理解数据内容,用数据产生价值 二、选择MQTT还是TCP长连接透传 1、原始的业务场景 2、端对端M2M场景——无人汽车 3、APP控制设备端场景——智能家居、智…

RK3588的GPU驱动和桌面环境

这里主要是以orange pi 5 plus为对象作一个简单的笔记 首先看rk3588的gpu介绍,它用的是ARM的GPU,支持openGL ES和openCL(支持什么其实跟GPU驱动有关,arm官方闭源GPU驱动就只支持这两个) opi官方提供了debian的xfce和…

Linux网络编程系列之服务器编程——多路复用模型

Linux网络编程系列 (够吃,管饱) 1、Linux网络编程系列之网络编程基础 2、Linux网络编程系列之TCP协议编程 3、Linux网络编程系列之UDP协议编程 4、Linux网络编程系列之UDP广播 5、Linux网络编程系列之UDP组播 6、Linux网络编程系列之服务器编…

ROS-6.参数的使用

参数的使用 参数服务结构命令行的使用方式运行小海龟命令介绍查看参数获取参数值设置参数保存参数到文件从文件导入参数 通过程序操作创建节点修改cmake编译运行 参数服务结构 ros中存在参数服务管理服务,管理这所有参数,所有节点剋订阅和发布这些节点 …

第三章 内存管理 三、覆盖与交换

目录 一、覆盖技术 二、交换技术 三、总结 一、覆盖技术 1、在覆盖技术中,我们要找到程序的调用结构。 2、因为这些程序不可能同时被调用(互斥调用),所以我们只需要选出需要空间最大的程序。 3、在物理内存中开拓一片与最大程…