了解C++编译与链接

了解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文件。

set_preprocesstofile

g++

常用的几个参数配置

1
2
3
4
5
6
7
-B <directory>           将<directory>添加到编译器的搜索路径中。
-v 显示被编译器调用的程序。
-### 与-v类似,但选项加引号,命令不执行。
-E 仅仅预处理; 不进行编译,汇编和链接
-S 仅编译; 不进行汇编和链接.
-c 编译和汇编,但是不链接.
-o <file> 执行输出文件.

图示:



关注博客或微信搜索公众号多媒体与图形,获取更多内容,欢迎在公众号留言交流!
扫一扫关注公众号
作者

占航

发布于

2022-04-30

更新于

2023-10-04

许可协议

评论