编译和编译器
对于计算机科学来说“编译”是一个很重要的概念,它指的是利用编译器从源语言编写的源程序产生目标程序的过程。对于计算机而言真正能识别的语言是2进制语言,但是在我们在进行软件开发的时候是不太可能直接用二进制语言进行开发的,那么问题来了,软件工程师开发出来的代码是怎么转变成计算机能识别的2进制语言呢?答案就是编译!编译的过程就是把人所写的代码“翻译”成2进制语言的过程,也就是从人的语言到机器的语言的过程。
编译器是一种计算机程序,它会将用某种编程语言写成的源代码,转换成另一种编程语言。它主要的目的是将便于人编写、阅读、维护的高级计算机语言所写作的源代码程序,翻译为计算机能解读、运行的低阶机器语言的程序,也就是可执行文件。编译器将原始程序(Source program)作为输入,翻译产生使用目标语言(Target language)的等价程序。源代码一般为高阶语言,如Pascal、C、C++、C# 、Java等,而目标语言则是汇编语言或目标机器的目标代码(Object code),有时也称作机器代码(Machine code)。
编译过程
编译程序把一个源程序翻译成目标程序的工作过程分为五个阶段:词法分析、语法分析、语义检查和中间代码生成、代码优化、目标代码生成。而在整个编译的过程中还涉及表格管理和出错处理。
GCC
Linux下可用的编译器有GCC、EGCS和PGCC,其中最常用最受欢迎的编译器便是GCC。GCC(GNU Compiler Collection,GNU 编译器套件)是由GNU开发的编程语言编译器套装。
GCC原本只能处理C语言,后来很快地扩展变得可处理C++,并衍生出了一个名为G++的编译器,G++是专门用于编译C++语言的编译器。随着项目的发展GCC之后变得可处理Fortran、Pascal、Objective-C、Java、Ada,以及Go与其他语言。现已被大多数类Unix操作系统采纳为标准的编译器,GCC 同样适用于Windows。
GCC通常是跨平台软件的编译器首选。有别于一般局限于特定系统与运行环境的编译器,GCC在所有平台上都使用同一个前端处理程序,产生一样的中介码,因此此中介码在各个其他平台上使用GCC编译,有很大的机会可得到正确无误的输出程序。
GCC编译流程
源代码(.c) -【预处理】→ 预处理文件(.i) -【编译】→ 汇编源代码(.s) -【汇编】→ 动态加载函数库文件(.o) -【链接】→ 二进可执行文件(通常无后缀)。
- 命令 gcc 在编译 C 语言程序为可执行程序的过程中,其实内部调用了不同的可执行程序,这些可执行程序隶属于 gcc 命令,或者说这些命令统称为 gcc 。
- gcc 调用 cpp 对源代码进行预处理,主要完成对源代码文件中包含(include)的头文件、预编译语句(如宏定义define等)的处理,例如对函数内部用到的宏变量进行替换等等。
- gcc 调用 cc1 编译预处理文件,将预处理文件内的 C 语言翻译成汇编代码,然后将翻译过来的汇编源代码保存在以“.s”为后缀的文件中。
- gcc 调用 as 对汇编源代码进行汇编处理,生成以“.o”为后缀的动态加载函数库文件。
- gcc 调用 ld 完成对一个或多个动态加载函数库文件的链接工作,创建一个可执行文件,将所有的动态加载函数安排到可执行程序的恰当位置。
GCC用法
gcc [参数] [文件名]
g++ [参数] [文件名]
gcc识别的文件扩展名如下:
.h://头文件
.c C //语言文件
.C、.cc、.cp、.cpp、.c++、.cxx //C++语言文件
.m://Objective-C 源代码文件
.i //预处理后的 C 语言文件
.ii //预处理后的 C++ 语言文件
.S //汇编文件(用户自己新建的汇编文件)
.s //预处理后的汇编文件
.o //编译后的目标文件
.a //目标文件的静态链接库(链接时使用)
.so //目标文件的动态链接库(链接、运行时使用)
编译选项说明
-x[语言]:指定编译的语言(C、C++、Object C等)
-c:只编译生成以“.o”为后缀名的动态加载函数库文件,而不链接成为可执行文件
-S:只编译生成以“.s”为后缀名的汇编源代码,而不汇编跟链接成为可执行文件
-E:只预处理生成预处理代码输出到标准输出,通常我们使用“-o”参数将其输出内容存储到以“.i”为后缀名的文件中
-o:用于指定生成文件的名字,而不采用默认名
-g:生成可执行文件的时候加上调试工具(GNU 的 gdb)所必需的符号信息,当需要执行 gdb 调试时使用
-O(或-O1):编译、链接过程执行优化处理,用于提高生的成可执行文件的执行效率
-O2:相比 -O 更高的优化级别
-O3:相比 -O2 更高的优化级别
-D:用于指向想要定义的宏
-w:禁止提示警告信息
-Wall:开启所有警告信息,用于严格编译
-l:用于指定需要用到的函数库名字或者头文件存储的目录
-L:用于指定函数库的存储目录
-v:显示编译器版本
参考资料
- http://baike.baidu.com/view/69568.htm
- https://zh.wikipedia.org/wiki/GCC
- http://www.ruanyifeng.com/blog/2014/11/compiler.html
- http://blog.csdn.net/tennysonsky/article/details/44920447
- http://www.ha97.com/2830.html
- http://ju.outofmemory.cn/entry/2051
- http://www.lai18.com/content/1270608.html
- http://blog.csdn.net/leeboy_wang/article/details/6629891