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,一经查实,立即删除!

相关文章

计算机网络(一)--网络发展和协议

网络发展和协议 计算机网络背景从独立模式到网络互联模式计算机网络发展七个阶段1. 批处理2. 分时系统3. 计算机之间的通信4. 计算机网络的产生5. 互联网的普及6. 以互联网技术为中心的时代7. 单纯建立连接 到 安全建立连接 协议例子:人与人之间的对话计算机中的协议 协议分层O…

Linux CentOS基础操作

Linux CentOS基础操作 1. 查看Linux服务器当前主机名等 hostname 2. 查看当前系统日期和时间 date -d -y 3. 显示网络接口信息,获取当前网卡状态,启动、停止网卡,网卡等闪烁显示30秒,配置网卡(网卡名称:eth1)的IP地址…

Redis主从同步机制

Redis主从同步机制是一种分布式数据库架构设计,用于确保主数据库(Master)和从数据库(Slave)之间的数据一致性,从而实现数据冗余、负载均衡、故障转移等功能。以下是Redis主从同步机制的关键要点&#xff1a…

每日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…

目标检测YOLO实战应用案例100讲-基于卷积神经网络的多尺度特征融合目标检测

目录 前言 存在的挑战 2 相关技术基础 2.1 卷积神经网络 2.2 损失函数

【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…

Netty框架介绍并编写WebSocket服务端与客户端

一、Netty 介绍 Netty 是一个基于 Java NIO(Non-blocking I/O,非阻塞 I/O)的网络通信框架,旨在帮助开发者轻松地编写高性能、高可靠性的网络应用程序。由于其出色的设计和强大的功能,Netty 在企业级应用和开源项目中得…

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

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

不同的子序列-java

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

小型企业网络安全指南

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

hyperf websocket

composer require hyperf/websocket-server 配置 Server 修改 config/autoload/server.php&#xff0c;增加以下配置。 <?phpreturn [servers > [[name > ws,type > Server::SERVER_WEBSOCKET,host > 0.0.0.0,port > 9502,sock_type > SWOOLE_SOCK_TCP…

2024年河北省网络建设与运维-省赛-nginx 和tomcat 服务服务步骤

题目&#xff1a; 5.nginx 和tomcat 服务 任务描述&#xff1a;利用系统自带tomcat&#xff0c;搭建 Tomcat网站。 &#xff08;1&#xff09;配置 linux2 为 nginx 服务器&#xff0c;网站目录为/www/nginx&#xff0c;默认文档 index.html 的内容为“HelloNginx”&#xf…

Rust与Go的对比

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