当前位置: 首页 > news >正文

【C语言】链接与编译(编译环境 )

前言:

在前面讲解文件操作,了解了文件的类别,文件的打开与关闭,字符读写函数, 字符串读写函数,格式化输入输出函数

在C语言编程中,编译与链接是将源代码转化为可执行程序的关键步骤。为了详细讲解这些过程及其相关知识点,我们将从以下几个方面展开,并结合实例进行说明:

环境

对C语言而言,生成程序的过程中存在两种环境:翻译环境 与 运行环境

  • 翻译环境:负责将C语言源代码转化为机器指令。这一过程包括预处理、编译、汇编和链接四个阶段。
  • 执行环境:运行编译后生成的可执行程序,通常依赖于操作系统和硬件资源

翻译环境

在翻译环境中,源代码会被转化为可执行的机器指令。这个过程会分为编译链接两大步。

 其中,编译分为:预处理,编译,汇编三个小步骤。而链接则是将多个.c文件与链接库进行链接,从而生成可执行程序。链接库,可以简单理解为库函数存储的地方,比如printf就需要链接到外部的库函数。

C程序编译过程与ELF可执行文件及gcc常见编译选项_c lion怎么编程elf文件-CSDN博客

编译

编译分为:预处理编译汇编三小步,接下来我们看看每一个阶段都什么作用。。

预处理

预处理阶段主要处理源代码中的预处理指令,如宏定义、文件包含和条件编译等。例如:

#define MAX(a, b) ((a) > (b) ? (a) : (b))

在预处理阶段,MAX宏会被展开为相应的表达式。 

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

在预处理阶段,MAX宏会被展开为相应的表达式。

示例
假设代码包含以下内容:
#include <stdio.h>
#define MAX(a, b) ((a) > (b) ? (a) : (b))int main() {int x = 10, y = 20;printf("Max value is: %d\n", MAX(x, y));return 0;
}

经过预处理后,MAX宏被展开为:

int main() {int x = 10, y = 20;printf("Max value is: %d\n", ((x) > (y) ? (x) : (y)));return 0;
}

Linux 高级编程 - 必备的 gcc 基础 登龙(DLonng)

预处理阶段会发生以下操作:

  1. 将头文件展开
  2. 删除#define指令,并执行宏的替换
  3. 删除注释代码

编译

在编译阶段,.i会被处理成为.s为后缀的⽂件

  • 词法分析:将源代码字符串分解成一系列的单词或符号(Token),如关键字、标识符、字面量、操作符等。
  • 语法分析:根据语言的语法规则,将Token串转换成一个体现语法规则的树状数据结构,即抽象语法树(AST)。这一步验证了源代码是否符合语言的语法规则。
  • 语义分析:在语法分析的基础上,进一步理解代码的含义,如变量类型、表达式求值等,并建立符号表以存储变量的作用域、类型等信息。
  • 中间代码生成:将AST转换为一种中间表示形式(IR),以便于后续的优化和跨平台执行。
  • 代码优化:对中间代码进行优化,以提高程序的运行效率。优化可能包括删除无用的代码、循环优化、常量折叠等。
  • 目标代码生成:将优化后的中间代码转换为汇编代码。这一步生成了特定于机器的代码,但尚未转换为机器语言指令。

以以下代码为例:

编译阶段将预处理后的代码转换为汇编语言,并进行语法分析、语义分析和优化。例如:

int add(int a, int b) 
{return a + b;
}

编译器会生成对应的汇编代码,如:

add:push ebpmov ebp, espmov eax, [ebp+8]add eax, [ebp+12]pop ebpret

示例
假设代码包含以下内容:

int square(int x) 
{return x * x;
}

编译后生成的汇编代码可能如下:

square:push ebpmov ebp, espmov eax, [ebp+8]imul eax, eaxpop ebpret

C语言 — 必学的编程基础语法,入门就从这里开始!_编程语法_C语言编程俱乐部的博 …

汇编

汇编阶段将汇编代码转换为机器语言目标文件(如.o文件)。例如:

section .text
global _start_start:mov eax, 1xor ebx, ebxint 0x80

汇编器会生成对应的机器码。

示例
假设代码包含以下内容:

section .text
global _start_start:mov eax, 1xor ebx, ebxint 0x80

汇编器生成的目标文件可能如下:

00000000 <_start>:0:   b8 01 00 00 00          mov    $0x1,%eax5:   31 db                 xor    %ebx,%ebx7:   cd 80                 int    $0x80

程序编译工具基础 - 知乎

链接

链接是⼀个复杂的过程,链接的时候需要把⼀堆⽂件链接在⼀起才⽣成可执⾏程序。
链接过程主要包括:地址和空间分配,符号决议和重定位等这些步骤。
链接解决的是

例如:

// file1.c
int add(int a, int b) {return a + b;
}

⼀个项⽬中多⽂件、多模块之间互相调⽤的问题

int main() {int result = add(5, 3);printf("Result: %d\n", result);return 0;
}

两个文件分别编译生成目标文件file1.ofile2.o,然后通过链接器将它们链接成可执行文件。

 

链接的大致过程就是:

先给外部变量一个假的地址,然后再在链接的时候,将所有假地址修正。

我们下章再见吧!!!! 

http://www.xdnf.cn/news/503695.html

相关文章:

  • 配置ssh服务-ubuntu到Windows拷贝文件方法
  • Java Records:简洁的数据建模新方式
  • ubuntu 24.04安装ros1 noetic
  • 历史数据分析——中证白酒
  • 数据库3——视图及安全性
  • 计算机网络体系结构深度解析:从理论到实践的全面梳理
  • 电动调节 V 型球阀:工业流体控制的全能解决方案-耀圣
  • 高考AI试题查询系统
  • 网络切片:给用户体验做“私人定制”的秘密武器
  • 80. Java 枚举类 - 使用枚举实现单例模式
  • 自制操作系统(三、文件系统实现)
  • 8天Python从入门到精通【itheima】-14~16
  • 【PhysUnits】4.2 Integer Trait
  • c/c++的opencv的轮廓匹配初识
  • 提升Qt应用性能--全面解析关键技术与策略
  • C++性能测试工具——Vtune的使用
  • BC 范式与 4NF
  • 全局异常处理:如何优雅地统一管理业务异常
  • Android屏幕采集编码打包推送RTMP技术详解:从开发到优化与应用
  • 数据结构第七章(四)-B树和B+树
  • Linux `mkdir` 命令深度解析与高阶应用指南
  • [逆向工程]C++实现DLL卸载(二十六)
  • 【算法】分支限界法和贪心、动态规划、回溯、分治法的区别是
  • 围炉夜话:三体阅读分析PPT+文稿
  • Java--利用(堆)获取前k个最小元素
  • 非易失性存储技术综合对比:EEPROM、NVRAM、NOR Flash、NAND Flash和SD卡
  • ​哈夫曼树(Huffman Tree)
  • C++ 回调函数
  • 计算机视觉与深度学习 | Python实现EEMD-LSTM时间序列预测(完整源码和数据)
  • JavaScript基础-预解析