1226 字
6 分钟
C++入门 (一) : 编译与链接
2026-03-08

C++是如何工作的#

头文件#

带有#的为preprocessor statement,即预处理指令 该类指令发生在真正的编译之前 当编译器收到一个源文件时,做的第一件事情就是预处理所有预处理指令

#include <iostream>

即找到iostream文件,将该文件中的所有内容复制粘贴到目前的文件里 这些被 include 的文件一般被称为header file,即头文件

每个 cpp 程序都有一个类似main函数的东西,被称作entry point 后面了解到这个必须的原因在于.exe 可执行文件必须需要一个入口,可在设置中自定义入口点(不一定必须是 main function)

只有主函数可以不返回任何值,默认返回 0

preprocessor statement被评估后,我们的文件会被编译,这个阶段,编译器把我们的 cpp 代码转化为实际的机器码

编译器#

所有.cpp 文件都会被编译,.h 头文件不会被编译,它会通过 include 到 cpp 中,然后被编译 每个.cpp 文件都被编译成一个Object文件(.obj)

链接器#

将所有.obj 文件连在一起,成为一个.exe 文件

如果在项目文件中调用其他文件的函数,需要在当前文件中声明该函数,告诉编译器这个函数存在,至于这个函数在哪,怎么用,由链接器实现.

C++的编译器是如何工作的#

抽象语法树#

编译器的工作是把代码转化为constant data(常量数据)和instructions(指令),构建抽象语法树后开始生成机器代码。

cpp 中没有文件的概念,文件只是给编译器提供源码的一个方式

.cpp 告诉编译器用 c++编译->编译器当成一个translation unit->得到一个.obj

预处理(preprocessing)#

处理所有以 # 开头的指令,进行纯文本替换

常见预处理命令

  • #include : 指定包含的文件,预处理器会打开该文件,然后把里面的内容完整复制粘贴到当前代码文件中.
  • #define : #define INTEGER int 在代码中查找INTEGER,将其换成int
  • #if#endif : 判断if后面的条件,如果不为真就把if到endif的内容删去(不出现在.i文件中)

这一步完成后,会生成一个预处理后的中间文件(通常后缀是 .i

编译(Compilation)#

编译器将.i文件转为汇编语言的.asm(windows)/.s(Unix/linux)

汇编器将.asm(windows)/.s(Unix/linux)文件转化为.obj文件

C++的链接器是如何工作的#

一旦编译了文件,我们就需要一个叫Linking(链接)的过程,其主要工作是找到每个符号和函数的位置,并将他们链接在一起。由于编译时每个.cpp 都会变成.obj,我们如果要做一个很多.cpp 文件的项目时,每个文件实际没法沟通,因此需要Linker链接器。

就算你都写在一个文件里了,找到程序的entry point,也就是主函数在哪儿,也需要链接器来链接主函数和其他东西

如果一个函数在当前文件里声明了且没在其他文件中定义,只要不使用它,链接就不会发现错误. 但如果有个函数在当前文件中定义,同时在函数体中使用了声明了但不存在的函数(无法link到),尽管不使用这个新定义的函数,链接也会报错,因为不能保证其他文件没使用该函数.——这种情况可以使用static来声明新的函数,保证这个函数只在这个translation unit中有效

如果是在编译期间报错,报错代码 Error是以 C开头。 如果是在链接期间报错,报错代码 Error是以 LNK开头

报错#

Unresolved external symbol :另一文件的函数定义和当前文件函数声明有区别,若没有调用则不会报错。或者可通过static解决,可使链接只发生在文件内部。

Duplicate symbol: 有函数或者变量名字和签名相同,两个函数名字、返回值、参数相同,Linker 不知道链接哪个。很可能发生,比如.h 中调用,又#include到了别的文件中,就会造成此问题。

可通过static解决,使链接只发生在文件内部。原理是#include的是static的函数,只在当前translation unit中有效

或者inline。由于#include是直接将原函数copy过来,而将函数声明为inline后,这个函数被调用后,只会把函数体内的代码替换到调用的地方,而不复制声明.

推荐的方法是将函数声明都放在.h 头文件中,定义放在.cpp

C++入门 (一) : 编译与链接
https://dingfengbo.vercel.app/posts/c入门/01-c的编译与链接/
作者
Eureka
发布于
2026-03-08
许可协议
CC BY-NC-SA 4.0