编译错误以c开头(如c2065),链接错误以lnk开头(如lnk2019);gcc/clang中出现“undefined reference”或“ld”即为链接错误;声明未实现、未链接库、符号拼写不一致等均导致链接失败。

看错误信息开头是 C 还是 LNK
编译错误(Compilation Error)在 MSVC 下通常以 C 开头,比如 C2065(未声明的标识符)、C2143(语法错误:缺少“;”);链接错误(Linking Error)则以 LNK 开头,最常见的是 LNK2019(未解析的外部符号)和 LNK2001(未解析的外部符号,但定义在别处)。GCC/Clang 不用字母前缀,但错误行里会明确写 undefined reference to 'func' 或 collect2: error: ld returned 1 exit status —— 出现 ld(linker)就基本可以断定是链接阶段出的问题。
编译能过但 build 失败,大概率是链接错误
在 IDE(如 VS、Dev-C++)里,“编译”(Ctrl+F7)只处理单个源文件,生成 .obj/.o;“生成”(F5 或 Build)才会调用链接器。如果某个函数只声明没实现,编译单个 .cpp 文件不会报错,但 build 时链接器找不到符号定义,就会报错。
- 声明在
header.h里:void log_message(const char*); - 没在任何
.cpp中实现它 → 编译main.cpp成功,build 失败,报LNK2019 - 哪怕只在一个
.cpp里调用了它,链接器就必须找到定义,否则失败
常见链接错误的典型触发场景
不是所有“找不到函数”都该去补实现 —— 很多时候是忘了链接对应库或拼错了名字。
-
undefined reference to 'pthread_create':没加-lpthread链接选项(Linux)或没在项目设置里启用多线程库(Windows) -
undefined reference to 'sqrt':数学函数需显式链接-lm(GCC),而 C++ 标准库函数如std::sqrt一般不用,但裸sqrt(3.0)可能掉进 C 库陷阱 -
LNK2005: already defined in xxx.obj:同一个函数/变量在多个编译单元里定义了(比如把非 inline 函数实现在头文件里,又被多个 .cpp include) - 拼写不一致:
void PrintLog();声明了,但实现写成void printLog() { ... }→ 链接器认为这是两个不同符号
为什么有时候改了头文件却没报错?
因为预处理和编译是分离的。头文件只参与编译阶段的符号检查(比如类型是否匹配、是否有声明),不决定链接行为。即使你删了 #include "log.h",只要 main.cpp 里没调用 log_message(),链接器根本不会去找它 —— 它只管“被引用但未定义”的符号,不管“声明但未使用”的符号。
这也是最容易被忽略的一点:链接错误永远只对「实际被调用」的符号负责,而不是「所有声明过的」。所以如果你看到链接报错,先确认那个函数是不是真被某处代码执行路径触达了,而不是凭空怀疑头文件漏了什么。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











