详解C语言—编译与链接

news2024/11/19 1:34:40

目录

1、程序的翻译环境

2、C语言程序的编译+链接 

3、程序执行的过程:


1、程序的翻译环境

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

  • 第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。
  • 第2种是执行环境,它用于实际执行代码

计算机能够执行二进制指令,但是我们写出的C语言代码是文本信息,计算机不能理解,翻译环境将C语言代码翻译成二进制指令,二进制指令放在可执行程序中,执行环境进行执行二进制的代码。

每个 .c 文件单独经过编译器生成 .obj(.o)目标文件,这个过程叫作“编译”,多个目标文件加上链接库经过链接器的处理生成“可执行程序”,链接器处理的过程叫链接。

我们之所以能够使用库函数,是因为这些函数被编译并存储在静态库(也称为静态链接库)中(后缀为 .LIB)。

当我们使用scanf时,在vs编译器中自动将”目标文件和链接库“通过链接器生成可执行程序。

 

2、C语言程序的编译+链接 

vs2022 是集成开发环境

集成了:编译器 + 链接器 + 调试器

将 .c 文件翻译成可执行程序需要两个操作:编译和链接 。

编译中分为三个过程:预编译、编译和汇编。 

在VS这样的集成开发环境中不方便观察这些细节,可以使用Linux系统上使用gcc编译器演示整个过程。 

ELF格式和段表:

在Linux下,GCC编译器产生的目标文件(如test.o)和可执行程序都使用ELF格式来存储。ELF格式与程序的存储和加载密切相关,其中段表是一个关键概念:

  1. ELF格式:ELF(Executable and Linkable Format)是一种通用的二进制文件格式,用于存储可执行程序、共享库和目标文件的信息。ELF文件包括有关程序结构和布局的重要信息。

  2. 段表:在ELF格式中,段表是一个重要的数据结构,用于描述可执行程序或目标文件中的各个段(segments)。段可以包括代码段、数据段、BSS段等,每个段都有其自己的属性和数据。段表记录了每个段的位置、大小、权限等信息。 

预处理: 在编译之前,C编译器会对源代码进行预处理。在这个阶段,预处理器会处理源代码中的预处理指令,如#include#define等,展开宏定义,将头文件的内容插入到源文件中,以及去除注释。预处理器生成的输出通常是一个经过预处理的中间文件。

编译: 编译器将预处理后的源代码翻译成汇编语言。这个阶段包括词法分析、语法分析、语义分析、符号汇总等步骤,以生成一个表示程序的中间表示形式。编译器的输出通常是一个或多个目标文件,这些文件包含了程序的机器码和相关信息。

 符号汇总

编译器首先会分析源代码,识别并收集所有变量和函数的名称。这是为了构建一个符号表,其中包括全局符号(如globalVar和myFunction)以及局部符号(如localVar如下图)。每个符号都会被分配一个唯一的地址或标识符,以便在后续的编译和链接阶段引用。

#include <stdio.h>

int globalVar = 42;

void myFunction(int x) {
    printf("Parameter: %d\n", x);
}

int main() {
    int localVar = 10;
    myFunction(localVar);
    return 0;
}

汇编: 汇编器将中间表示形式翻译成目标平台的机器码或汇编语言。这个阶段生成的文件通常是包含二进制机器码的目标文件,同时形成符号表。 

符号表是一个数据结构,用于存储程序中所有的符号信息,包括名称、类型、地址或标识符等。编译器在编译过程中会构建符号表,以便在后续的链接和代码生成阶段使用。

链接: 编译过程中的合并段表、符号表的合并和重定位是与链接器相关的关键步骤,用于将多个源文件编译成一个可执行文件或共享库。如果程序由多个源文件组成,链接器将这些目标文件合并在一起,解决外部符号引用,并生成最终的可执行文件。这个阶段还包括对标准库和其他共享库的链接,以满足程序的依赖关系。

合并段表:

        在编译和链接过程中,源代码被分成不同的段(segments)或节(sections),如代码段、数据段、堆栈段等。这些段包含了不同类型的程序代码和数据。合并段表是指将来自不同源文件的相同类型的段合并成一个大的段,以便在最终的可执行文件或共享库中有效组织和管理代码和数据。

        例如,如果你有多个源文件,每个都包含一个名为main的代码段,链接器将合并这些代码段以创建一个名为main的单一代码段。

符号表的合并:

        符号表是一个记录程序中定义和引用的所有符号(如变量、函数、常量等)的表格。在编译过程中,每个源文件都会生成一个局部符号表,记录该文件内部定义的符号。链接器的任务之一是将这些局部符号表合并成一个全局符号表,以确保在整个程序中可以正确解析符号的引用和定义。

        例如,如果在不同的源文件中都定义了一个名为counter的变量,链接器会合并这些定义,以便在整个程序中只有一个counter符号。

重定位:

        重定位是链接过程的重要步骤,用于解决在不同模块中引用的符号的地址问题。当一个模块引用另一个模块中的符号时,链接器需要确保这些引用正确指向符号的实际地址。这就涉及到重定位操作。

        链接器会扫描所有模块,找到符号引用并将其关联到正确的符号定义。这可能涉及修改代码中的地址或生成一个跳转表来跟踪符号的地址变化。这确保了在最终可执行文件或共享库中,符号的引用与其实际定义相匹配

生成可执行文件: 最终,链接器将生成的目标文件转换为可执行文件的格式,通常具有.exe(Windows)或无扩展名(Linux)的文件名,这个可执行文件包含了程序的机器码、数据、元数据以及其他必要信息。

例如:我们有两个源文件 main.c 和 helper.c 

编译: 每个源文件都独立编译为目标文件。这会产生例如 main.o 和 helper.o 这样的目标文件。每个目标文件都有自己的局部符号表,其中列出了该文件中定义的所有符号(如函数和全局变量)和它们的地址。

链接: 链接器的主要任务之一是合并所有目标文件的局部符号表以创建一个全局符号表。这个表中列出了程序中所有的符号及其地址。链接器还解决了所有目标文件中的外部符号引用,确保它们指向正确的地址。

+-------+           +-------+       +-------+              +-------+
| main.c|  ----1--->|编译器   | --2--> |main.o  | --3--(汇总)--->  |可执行文件   |
+-------+           +-------+       +-------+              +-------+
                                          |
+-------+           +-------+             |
|helper.c|  ----1--->|编译器   | ------->  |helper.o|
+-------+           +-------+       +-------+
                                          |
                                      (符号汇总)
                                          |
                                      +-------+
                                      |全局符号表|
                                      +-------+

符号汇总过程:

  • 对于每个目标文件(如 main.o 和 helper.o),查看其局部符号表。
  • 合并这些局部符号表以创建全局符号表。这个全局符号表列出了整个程序的所有符号。
  • 解决目标文件中的外部符号引用,确保它们指向正确的地址。

3、程序执行的过程:

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

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

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

相关文章

基于SSM的电动车上牌管理系统(有报告)。Javaee项目。

演示视频&#xff1a; 基于SSM的电动车上牌管理系统&#xff08;有报告&#xff09;。Javaee项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring SpringM…

【3】c++设计模式——>UML表示类之间的关联关系

关联关系 关联&#xff08;Assocition&#xff09;关系是类与类之间最常见的一种关系&#xff0c;它是一种结构化的关系&#xff0c;表示一个对象与另一个对象之间有联系&#xff0c;如汽车和轮胎、师傅和徒弟、班级和学生等。在UML类图中&#xff0c;用&#xff08;带接头或不…

JVM篇---第一篇

系列文章目录 文章目录 系列文章目录一、知识点汇总二、知识点详解:三、说说类加载与卸载一、知识点汇总 JVM是Java运行基础,面试时一定会遇到JVM的有关问题,内容相对集中,但对只是深度要求较高. 其中内存模型,类加载机制,GC是重点方面.性能调优部分更偏向应用,重点突出实践…

专业图标制作软件 Image2icon 最新中文 for mac

Image2Icon是一款用于Mac操作系统的图标转换工具。它允许用户将常见的图像文件&#xff08;如PNG、JPEG、GIF等&#xff09;转换为图标文件&#xff08;.ico格式&#xff09;&#xff0c;以便在Mac上用作应用程序、文件夹或驱动器的自定义图标。 以下是Image2Icon的一些主要功…

基于vc6+sdk51开发简易文字识别转语音的程序

系统&#xff1a;window7 软件&#xff1a;vc6.0 目的&#xff1a;简易文字转语音真人发声 利用2023国庆小长假&#xff0c;研究如何将文言转语音&#xff0c;之前在网上查询相关知识&#xff0c;大致了解微信语音转换&#xff0c;翻译官之类软件的原理&#xff0c;但要加入神…

python二次开发CATIA:旋转楼梯

旋转楼梯&#xff0c;也称为螺旋形或螺旋式楼梯&#xff0c;是一种围绕单柱或中心轴旋转而上的楼梯类型。由于其流线造型美观、典雅&#xff0c;并且能够节省空间&#xff0c;因此受到很多人的喜爱。这种楼梯最早可以追溯到公元前1000年左右&#xff0c;当时在所罗门王的宫殿中…

【4】c++设计模式——>UML表示类之间的聚合关系

聚合关系表示整体与部分的关系&#xff0c;在聚合关系中&#xff0c;成员对象时整体的一部分&#xff0c;但是成员对象可以脱离整体对象独立存在&#xff0c;当整体被析构销毁的时候&#xff0c;组成整体的这些子对象是不会被销毁的&#xff0c;是可以继续存活&#xff0c;并在…

Matlab论文插图绘制模板第117期—气泡云图

之前的文章中&#xff0c;分享了Matlab气泡图的绘制模板&#xff1a; 进一步&#xff0c;分享一种特殊的气泡图&#xff1a;气泡云图&#xff0c;先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源群中&#xff0c;加群的朋友请自行下载。有…

【STL】用哈希表(桶)封装出unordered_set和unordered_map

⭐博客主页&#xff1a;️CS semi主页 ⭐欢迎关注&#xff1a;点赞收藏留言 ⭐系列专栏&#xff1a;C进阶 ⭐代码仓库&#xff1a;C进阶 家人们更新不易&#xff0c;你们的点赞和关注对我而言十分重要&#xff0c;友友们麻烦多多点赞&#xff0b;关注&#xff0c;你们的支持是我…

如何在企业网站里做好网络安全

在当今数字时代&#xff0c;网站不仅仅是企业宣传和产品展示的平台&#xff0c;更是日常生活和商业活动中不可或缺的一部分。然而&#xff0c;随着网络技术不断发展&#xff0c;网站的安全问题日益凸显。保护网站和用户数据的安全已经成为至关重要的任务&#xff0c;以下是一些…

C#学生选课及成绩查询系统

一、项目背景 学生选课及成绩查询系统是一个学校不可缺少的部分&#xff0c;传统的人工管理档案的方式存在着很多的缺点&#xff0c;如&#xff1a;效率低、保密性差等&#xff0c;所以开发一套综合教务系统管理软件很有必要&#xff0c;它应该具有传统的手工管理所无法比拟的…

进程间通信-内存映射

内存映射是通过将一个进程的虚拟内存空间映射到另一个进程的虚拟内存空间来实现的。这样&#xff0c;两个进程可以共享同一块物理内存&#xff0c;从而实现数据的共享。内存映射通常通过操作系统提供的特定系统调用来完成。 下面是使用内存映射进行进程间通信的一般步骤&…

29 drf-Vue个人向总结-2

文章目录 drf项目总结2重写create自定义验证类获取个性化内容 与 lookup_field 的用处重写get_queryset&#xff0c;get_serializer_class类docs帮助文档支付宝支付原理&#xff08;微信同原理&#xff09;使用流程创建公钥私钥使用的理论介绍使用的代码介绍支付宝与Drf的联合使…

扫雷 | C语言 | 简单易懂 | 扫雷相关知识点总结

扫雷思路 相信大家都有玩过扫雷吧&#xff01;其实在我们学习完C语言中函数和数组之后&#xff0c;我们就有能力制作一个简单的扫雷小游戏了。 先考虑扫雷游戏的思路&#xff1a; 扫雷游戏我们需要利用二维数组将其进行初始化以及赋值“雷”&#xff0c;就以9*9个雷盘来分析…

集合-Map系列

系列文章目录 1.集合-Collection-CSDN博客​​​​​​ 2.集合-List集合-CSDN博客 3.集合-ArrayList源码分析(面试)_喜欢吃animal milk的博客-CSDN博客 4.数据结构-哈希表_喜欢吃animal milk的博客-CSDN博客 5.集合-set系列集合-CSDN博客 6.集合-Map系列-CSDN博客 文章目…

指针详解第三部分

1. 字符指针变量 一种指针类型为字符指针 char*&#xff08;下面有两个代码表示了两种不同的用法&#xff09; int main() {char ch w;char* pc &ch;*pc w;return 0; }int main() {const char* pstr "hello bit.";//这⾥是把⼀个字符串放到pstr指针变量⾥了…

什么是JWT?深入理解JWT从原理到应用

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《ELement》。&#x1f3af;&#x1f3af; &#x1…

使用 Python 和 wxPython 进行批量文件扩展名替换

引言&#xff1a; 在日常的文件管理中&#xff0c;有时我们需要将一大批文件的扩展名进行替换。手动一个个重命名文件是一项繁琐的任务&#xff0c;但是使用 Python 编程语言和 wxPython 模块可以轻松地实现这一功能。本文将介绍如何使用 Python 和 wxPython 创建一个简单的图形…

Python学习笔记之分支结构与循环结构

Python学习笔记之分支结构与循环结构 一、分支结构 使用关键字if、elif、else 练习1&#xff1a;使用分支结构实现分段函数求值 """分段函数求值""" x float(input("x "))if x > 1:y 3 * x - 5 elif x < -1:y 5 * x 3…

开启创意思维,畅享Mindomo Desktop for Mac思维导图之旅

在数字化时代&#xff0c;我们需要一个强大而直观的工具来整理和展现我们的思维。Mindomo Desktop for Mac&#xff08;Mindomo&#xff09;作为一款免费的思维导图软件&#xff0c;将为您提供卓越的创意思维体验。 Mindomo拥有直观的界面和丰富的功能&#xff0c;让您能够方便…