C语言程序的编译与链接

目录

  • 1.翻译环境和运行环境
  • 2.翻译环境
    • 2.1 预处理(预编译)
    • 2.2 编译
    • 2.3 汇编
    • 2.4 链接
  • 3.运行环境

1.翻译环境和运行环境

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

  • 翻译环境:在这个环境中源代码被转换为可执⾏的机器指令(⼆进制指令)。
  • 执行环境:⽤于实际执⾏代码。

在这里插入图片描述


2.翻译环境

翻译环境是怎么将源代码转换为可执⾏的机器指令的呢?本篇文章将讲解一下翻译环境在这个过程中对源代码做的事。

翻译环境由两个大的过程组成:

  • 编译
  • 链接

而其中编译过程又可分为:预处理(预编译)编译汇编三个过程。


在这里插入图片描述


  • 一个c语言的项目中可能有多个源文件( .c文件 ),那它们会如何生成可执行程序( .exe文件)呢?

  • 首先它们会单独经过编译器处理生成对应的目标文件。(如 test.c -> test.obj)

    • 注:在Windows环境下的⽬标⽂件的后缀是.obj,Linux环境下⽬标⽂件的后缀是.o
  • 多个⽬标⽂件和链接库⼀起经过链接器处理⽣成最终的可执⾏程序。

    • 链接库是指运⾏时库(它是⽀持程序运⾏的基本函数集合)或者第三⽅库。(库文件的使用需要链接库)
  • 如果将编译拆分成三部分,那就变成以下过程:

在这里插入图片描述

2.1 预处理(预编译)

预处理阶段,源⽂件和头⽂件会被处理成为.i为后缀的⽂件。

处理规则如下:

  • 将所有的 #define 删除,并展开所有的宏定义。

  • 处理所有的条件编译指令,如: #if、#ifdef、#elif、#else、#endif

  • 处理 #include 预编译指令,将包含的头⽂件的内容插⼊到该预编译指令的位置(直接将头文件内容全部拷贝过来,并删除 #include 这一行)。这个过程是递归进⾏的,也就是说被包含的头⽂件也可能包含其他⽂件。

  • 删除所有的注释

  • 添加⾏号和⽂件名标识,⽅便后续编译器⽣成调试信息等。

  • 或保留所有的 #pragma 的编译器指令,编译器后续会使⽤。

2.2 编译

编译阶段,会生成由汇编语言构成的汇编文件( .s 文件)

生成汇编文件的过程中会进行如下处理:

  • 语法分析
  • 词法分析
  • 语义分析
  • 符号汇总(将全局变量名或者函数名汇总,包括 main ,局部变量因为在编译过程还没有创建,只有运行时才创建,所以不汇总)

2.3 汇编

汇编阶段,会将汇编代码处理成机器指令(二进制指令),生成 .o 文件( Linux 环境下)或者 .obj 文件( Windows 环境下)。

同时还会形成符号表,符号表就是将之前汇总的符号与一个地址关联起来。
对一个函数名:

  • 如果文件中定义了该函数,则关联一个有效的地址(可以找到该函数并使用)
  • 如果文件中只声明了该函数,则关联一个无效的地址(给什么样的无效地址取决于编译器)。

2.4 链接

链接是将多个源文件和链接库一起经过链接器处理生成可执行文件的过程。

该阶段主要进行:

  • 段表合并
  • 符号表的合并和符号表的重定位

段表合并:经过汇编过程,生成的 .o 文件,如 test.oadd.o 等,都有具体的格式:elf 格式,格式将文件划分为不同的区域,存放不同的内容,所以将多个源文件合并生成可执行程序时,需要将相同的区域的内容合并到一起,这一过程称为合并段表

符号表的合并和重定位:汇编阶段每个源文件都形成了对应的符号表,在链接阶段需要将它们合并起来。下面举一个例子:

例如:在一个c语言项目中有 add.c (只定义了 函数 add)和 test.c (声明了但没有定义函数 add,且有主函数 main)。
add.o 中的符号表:

add -> 0x11111111  //(假设的有效地址)

test.o 中的符号表:

add -> 0x00000000   //(假设的无效地址)
main -> 0x22222222   // (假设的有效地址)

因为 test.o 中和 add.o 中都有 add ,但是 add.o 中的地址是无效的,所以合并后取有效地址,这个过程叫符号表的重定位

add -> 0x11111111  //(假设的有效地址)
main -> 0x22222222   // (假设的有效地址)

有了符号表程序就可以找到对应的函数,如果合并之后某个符号的地址仍是无效的,则程序无法找到这个符号的定义并报错

add -> 0x00000000   //(假设的无效地址)
main -> 0x22222222   // (假设的有效地址)

合并后这样的符号表程序就会报错。

3.运行环境

  1. 程序必须载⼊内存中。在有操作系统的环境中:⼀般这个由操作系统完成。在独⽴的环境中,程序的载⼊必须由⼿⼯安排,也可能是通过可执⾏代码置⼊只读内存来完成。

  2. 程序的执⾏便开始。接着便调⽤ main 函数。

  3. 开始执⾏程序代码。这个时候程序将使⽤⼀个运⾏时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使⽤静态(static)内存,存储于静态内存中的变量在程序的整个执⾏过程⼀直保留他们的值。

  4. 终⽌程序。正常终⽌ main 函数;也有可能是意外终⽌。

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

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

相关文章

每日OJ题_两个数组dp⑤_力扣10. 正则表达式匹配

目录 力扣10. 正则表达式匹配 解析代码 力扣10. 正则表达式匹配 10. 正则表达式匹配 难度 困难 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 . 和 * 的正则表达式匹配。 . 匹配任意单个字符* 匹配零个或多个前面的那一个元素 所谓匹配&#xff0c…

springboot 整合 mybatis(配置版)

代码及配置整合 创建实体类,与数据库对应 创建 mapper、service 和 controller @AutowiredUserService userService;@ResponseBody@GetMapping("/user")public com.vazquez.bootstudy.model.User getById(@RequestParam("id") Long id) {return userServ…

XC7A35T-2FGG484 嵌入式FPGA现场可编程门阵列 Xilinx

XC7A35T-2FGG484 是一款由Xilinx(赛灵思)制造的FPGA(现场可编程门阵列)芯片 以下是XC7A35T-2FGG484 的主要参数: 1. 系列:Artix-7 2. 逻辑单元数量:33280个 3. 工艺技术:28nm 4. …

设计模式之中介者模式讲解

概念:也称为调停者模式。用一个中介者对象封装一系列对象的交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。 抽象中介者:定义中介者的操作。具体中介者:实现…

【HTML】简单制作一个动态变色光束花

目录 前言 开始 HTML部分 效果图 ​编辑​编辑​编辑​编辑总结 前言 无需多言,本文将详细介绍一段代码,具体内容如下: 开始 首先新建文件夹,创建一个文本文档,其中HTML的文件名改为[index.html]&a…

【CTF】rip--堆栈的简单认识

前言 最近在学二进制,准备拿BUUCTF的pwn试试手,还在摸索的阶段,有什么思路出错的地方还请指出。 解题思路 下载文件到kali,查看文件为 64-bit的ELF(ELF为Linux下的可执行文件,相当于Windows的exe&#xff0…

python-flask后端知识点

anki 简单介绍: 在当今信息爆炸的时代,学习已经不再仅仅是获取知识,更是一项关于有效性和持续性的挑战。幸运的是,我们有幸生活在一个科技日新月异的时代,而ANKI(Anki)正是一款旗舰级的学习工具…

GD32F470_GY-68 BMP180 新款 BOSCH温度 代替BMP085 气压传感器模块

2.23 BMP180气压传感器 1BMP180是一款高精度、小体积、低能耗的压力传感器,可以轻松应用在移动设备中.在测量海拔高度时,传统的做法是通过测量某一高度的大气压力,再经过换算才能得到高度数据。BMP180不仅可以实时的测量大气压力&#xff0c…

基于velero和minio实现k8s数据的备份

1.30部署minio rootk8s-harbor:/etc/kubeasz/clusters/k8s-cluster1# docker run \ -d --restartalways -p 9000:9000 -p 9090:9090 –name minio -v /data/minio/data:/data -e “MINIO_ROOT_USERadmin” -e “MINIO_ROOT_PASSWORD12345678” quay.io/minio/minio server…

智慧安防系统EasyCVR视频汇聚平台接入大华设备无法语音对讲的原因排查与解决

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台支持7*24小时实时高清视频监控,能同时播放多路监控视频流,视频画面1、4、9、16个可选,支持自定义视频轮播。EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标…

不同的子序列-java

题目描述(力扣题库115): 给你两个字符串 s 和 t ,统计并返回在 s 的 子序列 中 t 出现的个数,结果需要对 109 7 取模。 示例 1: 输入:s "rabbbit", t "rabbit"输出:3 解释: 如下所示…

小型企业网络安全指南

许多小型企业刚刚起步,没有大公司所拥有的相同资源来保护其数据。他们不仅可能没有资金来支持多样化的安全计划,而且也可能没有人力或时间。 网络犯罪分子知道小型企业缺乏这些资源,并利用这些资源来谋取利益。遭受网络攻击后,小…

Rust与Go的对比

在各个领域,Rust 都已经成为一流的语言。最近,我们通过将服务的实现从 Go 切换到 Rust,极大地提升了该服务的性能。这里我阐述了重新实现服务为何是有价值的、该过程是如何实现的以及由此带来的性能提升。 Read States 服务 我们从 Go 切换…

01 Php学习:导学篇

Php是什么? PHP 是服务器端脚本语言。 PHP(Hypertext Preprocessor)是一种通用开源脚本语言,主要用于服务器端开发。PHP脚本在服务器端执行,生成动态网页内容或执行服务器端任务。PHP可以嵌入到HTML中,也…

千视携 NDI 6 轻量化媒体方案亮相北京CCBN展会

展会简介 第30届中国国际广播电视网络技术展览会(CCBN)将于4月24至26日在北京首钢会展中心举行。此次展会将汇集全球各大数字媒体、广播电视单位以及IT、通信技术厂商。展会重点关注数字化转型、智能媒体、融媒体等主题,并展示最新的5G、4K/8…

【运输层】TCP 的可靠传输是如何实现的?

目录 1、发送和接收窗口(滑动窗口) (1)滑动窗口的工作流程 (2)滑动窗口和缓存的关系 (3)滑动窗口的注意事项 2、如何选择超时重传时间 (1)加权平均往返…

5.网络编程-socker(golang版)

目录 一、什么是socket? 二、Golang中使用TCP TCP服务端 TCP客户端​​​​​​​ 三、TCP黏包,拆包 1.什么是粘包,拆包? 2.为什么UDP没有粘包,拆包? 3.粘包拆包发生场景 4.TCP黏包 黏包服务端 …

解决 IDEA每次打开新的项目都要重新设置maven问题

目录 一、当前项目设置maven 如下图: 二、设置打开的新项目的maven 如下图:​ 一、当前项目设置maven 对于当前项目我们都知道设置maven的配置要在 File -- Settings -- Build -- Maven 中设置 如下图: 二、设置打开的新项目的maven F…

整理的微信小程序日历(单选/多选/筛选)

一、日历横向多选&#xff0c;支持单日、双日、三日、工作日等选择 效果图 wxml文件 <view class"calendar"><view class"section"><view class"title flex-box"><button bindtap"past">上一页</button&…

stm32与esp8266WIFI模块

硬件介绍 WIFI模块ESP-01S 使用AT指令控制1-ESP8266-AT指令初试化及部分基础知识_ch_pd-CSDN博客 项目需求 通过ESP-01SWIFI模块控制LED状态模拟插座 串口1用于与ESP8266通讯&#xff0c;串口2连接PC&#xff0c;用于打印log&#xff0c;查看系统状态 项目接线 将WIFI模块的…