C++学习笔记(一)编译器与链接器
前言
本系列笔记根据B站网课BV1Dk4y1j7oj记录。
编译器的作用
C++程序首先通过编译器生成中间文件。
一般而言,编译器通过文件后缀名决定如何对其进行处理(如.h文件作为被视为头文件,.cpp文件被作为编译单元^1进行编译)。
编译器首先对程序进行预处理。常用的预处理命令有#include、#define、#if、#ifdef、#ifndef、endif、#pragma等。
这里只举例讲解其中的几个:
#include
该命令把所引用的头文件内容原封不动地直接粘贴到命令位置。
PS:#include指令的三种类型
- #include<xxx.h>
这种#include指令所引用的头文件,编译时会去系统目录寻找。
- #include”xxx.h”
这种#include指令所引用的头文件,编译时会去当前目录(即包含该#include指令的文件所在的目录)寻找,若没找到再去系统目录寻找。
- #include <xxx>
同第一种,C++标准下的新写法。
#define
该命令查找文件中的特定字符并进行替换。(如#define int long long把文件中所有的int替换成long long)。
在预处理结束之后,编译器还会对程序进行语法检查、优化等步骤。
链接器的作用
编译器生成的中间文件经过链接器链接后生成最终的可执行文件。
要注意链接阶段可能发生的重定义问题。在C和C++中,声明(Declaration)和定义(Definition)非常不同^3,通常可以有多次声明,但只能有一次定义。
当编译 / 链接过程中出现对同一件东西(变量、函数、类……)的多次定义,就会导致重定义问题。
比如,一个头文件(a)中包含了某物的定义,而另一个头文件(b)包含了a,当一个cpp文件同时引用a和b时,预处理阶段会把a中内容复制进b,再把a和b都复制进最终文件中,链接阶段就会因重定义问题报错。
为了避免重定义问题,要注意.h文件中尽量只放声明,而.cpp文件中尽量只放定义。
也可以使用下面的头文件写法(被称为标准头文件格式)避免重定义问题。
1 | #ifndef AAA_H//即“if not define”。只有没有定义过一个名为AAA_H(不固定,根据具体情境命名)的宏时,才编译该语句到endif语句间的内容。 |
该格式通过条件编译语句(#ifndef和#endif),实现了只有在第一次引用该头文件时才复制其中内容到源文件中。
当重复引用该头文件时,文件中内容会因为已经存在宏AAA_H而不编译。




