编译和链接笔记


对于平常的应用程序开发,我们很少需要关注编译和链接过程,因为通常的开发环境都是流行的集成开发环境(IDE),比如visual studio等,这样的IDE一般都将编译和链接的过程一步完成,通常将这种编译和链接合并在一起称为构建。即使使用命令行来编译一个源代码文件,简单的一句"hello.c"就包含了非常复杂的过程。
IDE和编译器提供的默认设置,编译和链接参数对于大部分的应用程序开发而言已经足够使用了,但是在这样的开发过程中,我们往往会被这些复杂的集合工具所提供的强大功能所迷惑,很多系统软件的运行机制与机理被掩盖,其程序的很多莫名其妙的错误让我们无法适从,面对程序运行的种种性能瓶颈我们束手无策。我们看见的是这些问题的现象,但是却很难看清本质,如果能深入了解这些机制,那么解决这些问题就能够游刃有余,收放自如了。

被隐藏了的过程

c语言入门程序hello world

#include <stdio.h>
int main()
{
  printf("Hello world\n");
  return 0;
}

事实上,上述过程可以分为4个步骤,分别为预处理,编译,汇编和链接。

预编译

首先是源代码文件hello.c和相关的头文件,如stdio.h等被预编译器cpp预编译成一个.i文件。对于C++程序来说,它的源代码文件的扩展名可能是.cpp或.cxx,头文件的扩展名可能是.hpp,而预编译后的文件扩展名是.ii。第一步预编译的过程相当于如下命令(-E表示只进行预编译)
$gcc -E hello.c -o hello.i
或者:
$cpp hello.c > hello.i
预编译过程主要处理那些源代码文件中的以“#”开始的预编译指令,比如"#include",“define"等,主要处理规则如下:
1.将所有的”#define"删除,并且展开所有的宏定义。
2.处理所有条件预编译指令,比如"#if","#ifdef","#elif","#else","#endif"。
3.处理"#include"预编译指令,将被包含的文件插入到该预编译指令的位置。注意,这个过程是递归进行的,也就是说被包含的文件可能还包含其他文件。
4.删除所有注释"//“和”/* */".
5.增加行号和文件标识,比如#2"hello.c" 2,以便于编译时编译器产生调试用的行号信息以及用于编译产生编译错误或警告时能显示行号。
6.保留所有的#pragma编译器指令,因为编译器必须要使用它们。
经过预编译后的,i文件不包含任何宏定义,因为所有的宏已经被展开,并且包含的文件也已经被插入到.i文件中。所有当我无法判断宏定义是否正确或头文件包含是否正确时。可以查看预编译后的文件来确定问题。

编译

编译过程是把预处理完的文件进行一系列词法分析,语法分析,语义分析及优化后生产相应的汇编代码文件,这个过程往往是我们所说的整个程序构建的核心部分,也是最复杂的部分,这涉及编译原理等一些内容。上面的编译过程相当于如下命令:
$gcc -s hello.i -o hello.s
现在版本的GCC把预编译和编译两个步骤合并成一个步骤,使用了一个叫做ccl的程序来完成这两个步骤,我们也可以直接调用ccl来完成它或者使用如下命令:
$gcc -s hello.c -o hello.s
都可以得到汇编输出文件hello.s,对于C语言的代码来讲,这个预编译和编译的程序是ccl,对于C++来说,有对应的程序叫做cclplus。所以实际上gcc这个命令只是这些后台程序的包装,它会根据不同的参数要求去调用预编译编译程序cc1,汇编器as,链接器Id。

汇编

汇编器是将汇编代码转变成机器可执行的指令,每一个汇编语句几乎都对应一条机器指令,所有汇编器的汇编过程相对于编译器来讲比较简单,他没有复杂的语法,也没有语义,也不需要做指令优化,只是根据汇编指令和机器指令的对照表一一翻译就可以了。
上面的汇编过程我们可以调用汇编器as来完成:
$as hello.s -o hello.o
或者:
$gcc -c hello.s -o hello.o
或者使用gcc命令从C源代码文件开始,经过预编译,编译和汇编直接输出目标文件:
$gcc -c hello.c -o hello.o

链接

链接通常是个让人比较费解的过程,为什么汇编器不直接输出可执行文件而是输出一个目标文件?链接过程到底包含了什么内容?为什么要链接?在此之前,我们需要了解编译器担任了什么样的角色。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值