了解C++编译与链接
C++将源码到可执行文件,有两个主要的操作:编译(compiling)和链接(linking)。
编译
编译器唯一要做的事情就是将源码文本变为obj格式的文件,然后obj文件会传入链接器,由链接器完成转变为二进制执行文件。
编译单元
在一个C++工程里,每个cpp文件都会被编译成一个obj文件,这些cpp文件也叫编译单元(translation unit)。
请记住,本质上c++根本不在乎文件,什么后缀格式的文件并不重要。不像java中,编译单元必须后缀为.java文件,类名需要和文件名相同,但是c++完全不需要,文件只是给编译器提供源代码。
如果你创建了一个.h文件,编译器会把它当成头文件,如果创建.cpp
文件,编译器会把他当成c++文件,如果创建一个.c
文件,编译器会把它当成c文件去处理。这是默认的设定,但是实际上,我们完全可以改变这些写法,我们可以创建一个任意的文件格式,例如.hang后缀的文件,然后告诉编译器这是个c++文件,要按c++文件去编译它,这完全没问题。
当我们告诉编译器某种格式是c++文件,编译器会将这种文件当成一个编译单元,而一个编译单元最终会输出一个obj
文件。默认情况下,一个.cpp
格式文件就是一个编译单元。
有这么一种情况,你在一个cpp文件里include其他cpp文件,最后仅仅编译那一个cpp文件,虽然每个cpp源码都参与到编译过程了,但是其实只有一个编译单元,只会生成一个obj。因为预编译处理会生成一个很大的cpp文件参与编译。
几个常见的编译器
MSVC: 微软的VC编译器, Visual Studio自带的C/C++编译器。
gcc :GNU Compiler Collection(GNU编译器套装),支持更多的语言编译(C、C++、Fortran、Pascal、Objective-C、Java、Ada、Go等),是一套由GNU开发的支持多种编程语言的编译器。
clang是由苹果公司赞助开发的一套编译工具集,LLVM编译器工具集的一个用于编译C、C++、Objective-C的前端。
编译过程
编译的完整过程也分为几个重要步骤:
- 预处理: 预处理又称为预编译,是做些代码文本替换工作。通过预编译输出到.i文件 。
- 编译优化: 通过语法分析和词法分析,确定所有指令是否符合规则,之后翻译成汇编代码。 这个过程将.i文件转化位.s文件。
- 汇编: 汇编过程就是把汇编语言翻译成目标机器指令的过程,生成目标文件,目标文件中机器语言代码。 这个过程将.s文件转化成.o或者.obj文件。
目标文件由段组成,通常至少有数据段和代码段这样两个段 。**编译工作其实就是要将源码转换为常数资料(constant data)或者指令(instructions)**。
链接
一般来说一个c++文件通过编译最终生成一个.obj文件,但是它不能立即执行,需要通过链接过程生成最终的可执行文件
操作与调试
visual studio 操作
编译cpp文件
Ctrl+F7
只对当前所操作项目的.cpp
文件进行编译,对单个编译单元进行编译。
预处理
Visual Studio
中设置预处理到文件,然后Ctrl+F7
看到效果,会编译出来一个.i
文件。
g++
常用的几个参数配置
1 | -B <directory> 将<directory>添加到编译器的搜索路径中。 |
图示: