C语言程序目标文件详解:模块、链接与优化

需积分: 0 0 下载量 88 浏览量 更新于2024-08-05 收藏 505KB PDF 举报
目标文件格式概述是软件开发过程中至关重要的一部分,特别是在使用高级编程语言如C语言时。本文由南京大学计算机科学与技术系的袁春风撰写,于2015年6月,主要针对C语言程序的编译和链接流程进行深入讲解。 首先,作者通过一个简单的C语言示例来阐述程序结构,例如`main.c`和`swap.c`两个模块,它们各自包含代码和数据。`main.c`中定义了一个全局数组`intbuf[2]`和一个外部指针`int*bufp0`,而`swap.c`中有一个静态指针`static int*bufp1`和一个局部变量`temp`。局部变量`temp`存储在栈上,其生命周期仅限于函数内,不会在函数外部被访问。 程序编译和链接的过程可以分为几个步骤: 1. 使用GCC编译器进行编译和链接。例如,通过命令`gcc -O2 -g main.c swap.c`进行编译,`-O2`表示开启二级优化,`-g`则生成调试信息,`-o p`指定生成的目标文件名为`p`。 2. 源程序经过预处理器(cpp)、编译器(cc1)和汇编器(as)的处理,分别生成可重定位的目标文件(`.o`)。 3. 链接过程的核心是将这些目标文件合并,并解决符号引用。链接器会确定每个符号(如函数、变量等)的实际地址,并将它们插入到最终的可执行文件中,如`.text`区存放代码,`.data`区存放数据,`.bss`区存放未初始化的静态变量,`.symtab`用于符号表,`.debug`用于调试信息。 链接过程的关键步骤包括: - 符号解析:检查每个模块中的函数和变量引用,确保它们在其他模块中已经定义或存在。 - 合并.o文件:将所有相关的代码和数据合并到一个可执行文件中。 - 地址分配:为每个符号分配内存地址,这包括函数入口点、全局变量和静态变量。 - 更新指令地址:在指令中使用新的地址,以反映目标文件的合并和重定位。 文章中还提到,`main()`函数的入口点`addB`和`subB`等指令会根据链接后的地址调整,使得程序能够正确执行。此外,`int*bufp0`和`int*bufp1`等全局和静态变量的内存位置也会在链接阶段确定。 总结来说,本文详细解释了C语言程序如何通过编译器和链接器转化为可执行文件,涉及目标文件的结构、符号解析和链接操作,以及优化和调试选项的选择。这对于理解软件开发的底层工作原理和技术细节具有重要价值。