首先,编写最简单的C++代码并保存为main.cpp:
1 #include <iostream> 2 using namespace std; 3 4 int main(int argc, char* argv[]) 5 { 6 cout << "Hello world!" << endl; 7 return 0; 8 }
使用命令g++ main.cpp,将会编译连接得到可执行文件a.out,(这里需要明确的是g++会调用gcc,而gcc实际上包装了后台一些程序,根据不同的参数去调用相应的程序进行处理)。
事实上从源文件main.cpp到可执行文件a.out的过程包括了如下的4个主要步骤:
预处理(Preprocessing)
编译(Compliation)
汇编(Assembly)
链接(Linking)
1. 预处理
预处理调用预处理器cpp, 主要处理包括以下过程:
- 文件包含。处理#include预编译指令,将被包含的文件插入到该预编译指令所在位置。
- 条件编译。处理#if #indef #elif #else #endif 等条件预编译指令,主要是进行编译时进行有选择的挑选,注释掉一些指定的代码,以达到版本控制、防止对文件重复包含的功能。
- 布局控制。处理#progma预编译指令,为编译程序提供非常规的控制流信息。
- 宏替换。处理#define预编译指令,展开宏定义。
- 其它一些预处理工作,如删除所有注释 “//”和”/* */”,添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。
预处理命令:
gcc - E main.cpp -o main.i (或g++ -E main.cpp -o main.i)
-E 表示只进行预处理。也可以用命令cpp(the C Preprocessor)完成预处理:
cpp main.cpp > main.i
生成的 *.i 是预处理之后的代码。
2.编译
执行编译程序cc1plus(c语言则是cc1), 主要工作是把预处理完的文件进行一系列的词法分析,语法分析,语义分析及代码优化后生成相应的汇编代码。
命令:
gcc –S main.i –o main.s
或者
/usr/lib/gcc/i586-suse-linux/4.1.2/cc1plus main.cpp
如果是c源文件,则执行
/usr/lib/gcc/i586-suse-linux/4.1.2/cc1 main.c
生成的 *.s 是汇编代码。
3.汇编
执行汇编命令as, 是将汇编代码转变成机器可以执行的命令,每一个汇编语句几乎都对应一条机器指令。汇编相对于编译过程比较简单,根据汇编指令和机器指令的对照表一一翻译即可。
命令:
gcc -c main.cpp -o main.o
或者
as main.s -o main.o
4.链接
调用链接器ld, 链接程序运行所依赖的目标文件,以及所依赖的其它库文件,最后生成可执行文件。
ld -static crt1.o crti.o crtbeginT.o hello.o -start-group -lgcc -lgcc_eh -lc-end-group crtend.o crtn.o (省略了文件的路径名)。
链接部分需要注意的是:对于c++源程序,gcc不能自动和c++的库链接,所以只能使用g++来链接。
通常情况下,对C++源代码,我们直接使用g++命令完成了上述的所有过程。
g++ -o main main.cpp
g++ main.cpp
总结过程就是:
main.cpp -->预处理(cpp)--> main.i -->编译(as)--> main.s -->汇编(as)--> main.o(依赖的其它 *.o) -->链接(ld)--> main可执行程序