#include <stdio.h>
int main(int argc,char **argv)
{
printf("hello world\n");
return 0;
}
在linux下,使用GCC来编译helloworld 程序时,只需使用最简单的命令:
& gcc hello.cpp -o a
或$ gcc hello.cpp; $./a.out
即可在屏幕上输出hello world
事实上,上述过程可以分解为4个步骤,分别是预处理(Prepressing)、编译(Compilation)、汇编(Assembly)和链接(Linking),如下图所示:
1、预编译
首先是源代码文件hello.c和相关的头文件,如stdio.h等被预编译器cpp预编译成一个.i文件。对于C++程序来说,它的源代码文件的扩展名可能是.cpp或.cxx,头文件的扩展名可能是.hpp,而预编译后的文件扩展名是.ii。第一步预编译后的文件扩展名是.ii。第一步预编译的过程相当于如下命令(-E表示只进行预编译):
$ gcc -E hello.c -o hello.i
或者:$ cpp hello.c > hello.i
预编译过程主要处理那些原文件中以“#”开始的预编译指令。比如"#include"、"#define"等,主要处理规则如下:
>将所有的"#define"删除,并展开所有的宏定义。
>处理所有条件预编译指令,比如"#if"、"#ifdef"、"#elif"、"#else"、"#endif"。
>处理"#include"预编译指令,将被包含的文件插入到该预编译指令的位置。注意,这个过程是递归进行的,也就是说被包含的文件可能包含其它的文件。
>删除所有的注释"//"和"/**/"。
>添加行号和文件名标识,比如#2 "hello.c" 2,以便于编译时编译器产生调试用的行号信息及用于编译时产生编译错误或警告时能够显示行号。
>保留所有#pragma 编译器指令,因为编译器需要使用。
2、编译
编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后产生相应的汇编代码文件,这个过程是整个程序构建的核心部分。上例的编译部分相当于:
$ gcc -S hello.i -o hello.s
3、汇编
汇编器是将汇编代码转变成机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令。所以汇编器的汇编过程相对于编译器比较简单,他没有复杂的语法,也没有语义,也不需要做指令优化,只是根据汇编指令和机器指令的对照表一一翻译就可以了。上例的汇编过程可以用汇编器as来完成:
$ as hello.s -o hello.o
或者:
$ gcc -c hello.s -o hello.o
或者使用gcc命令从C源代码文件开始,经过预编译、编译和汇编直接输出目标文件(Object File):
$ gcc -c hello.c -o hello.o
4、链接
先总结至此,后续补充.......