C语言程序的编译+链接
时间:2022-11-21 19:00:00
引入:
1.程序翻译和执行环境
在ANSI C在任何实现中,都有两种不同的环境。
第一种是翻译环境,在这种环境下,源代码被转换为可执行的机器指令。
第二种是执行环境,用于实际执行代码。
<1>翻译环境
通过编译过程将构成程序的每个源文件转换为目标代码。(object code)。
(Windows文件后缀在环境中.obj,Linux后缀为环境.o)
每个目标文件由链接器链接(linker)捆绑在一起,形成单一完整的可执行程序。
链接器还将在标准C函数库中引入任何程序使用的函数,它可以搜索程序员的个人程序库,并将所需的函数链接到程序中。
简而言之,翻译环境是:源文件->编译、链接->可执行文件过程中的环境。
<2>执行环境
可执行程序运行的环境。
2.编译本身也分为几个阶段
<1>预编译:
预编译:gcc test.c -E(Linux)
1.包含头文件。
#inlcude是预处理指令
2、#define替换符号。
#define也是预处理指令
3.删除注释。
总结:文本操作预编译。
<2>编译:
编译:gcc test.i -S(test.i是预处理生成的文件)(生成test.s)(Linux环境下)
把C语言代码翻译成了汇编代码
包含了:
1、语法分析
2、词法分析
3、语义分析
*4.符号汇总(汇总全局符号、函数名(自定义函数)等。main,局部符号不会汇总)
(错误编不过去,报错)
<3>汇编:
汇编:gcc test.s -c(会生成test.o)(Linux环境下)
windows环境下的目标文件是.obj
Linux环境下的目标文件是.o
目标文件为二进制
将汇编指令翻译成二进制指令
形成符号表(形成编译过程中汇总的符号表,一个 一 对应)。
<4>链接:
将前几个文件和链接库放在一起
1、合并段表
2、符号表的合并和重命名(就是类似找到汇总的符号的有效地址,例如在源文件中声明了一个函数假设叫Func,如果有声明和定义,在符号汇总中会有两个Func所有的符号都是总结出来的Func收集函数声明Func符号实际上对应于无效地址,而由Func部分收集来自函数的函数Func符号对应有效地址,如果在链接中遇到相应的无效地址Func符号,会去符号表找到符号的有效地址,如果有,合并,如果没有,但使用这个函数,会报告错误,说Func函数未定义)。
3、运行环境
程序执行过程:
<1>程序必须包含在内存中。在有操作系统的环境中,该操作通常由操作系统完成。在一个独立的环境中,程序的载入由手动安排,或者可以通过将可执行代码放入可执行内存来完成。
<2>操作环境是程序一旦执行就开始,然后调用main主函数。
<3>开始执行程序代码。此时将使用堆栈(stack),存储函数的局部变量和返回地址。(创建和销毁函数栈帧)程序也可以使用静态内存(static)在程序的整个执行过程中,存储在静态内存中的变量始终保留其值。
<4>终止程序。正常终止main函数,也可能异常终止。
欢迎指正水平有限。