g++ -c 仅编译不链接,生成目标文件(.o),含机器码和符号引用但无实现,需后续链接才能运行;漏加-c会因尝试链接而报undefined reference等错误。

g++ -c 生成 .o 文件
直接用 g++ -c 就能生成目标文件,不链接、不生成可执行文件。这是最常用也最安全的方式,尤其适合多文件项目或需要增量编译的场景。
常见错误是漏掉 -c,比如写成 g++ main.cpp -o main.o —— 这实际会尝试链接,找不到 main 函数入口或标准库符号时直接报错:undefined reference to `main' 或 ld: cannot find -lc。
-
g++ -c main.cpp→ 默认输出main.o -
g++ -c main.cpp -o build/main.o→ 指定输出路径,推荐用于分离构建目录 - 多个文件:分别执行
g++ -c a.cpp、g++ -c b.cpp,得到a.o和b.o,后续再统一链接
目标文件里有没有 #include 的实现?
没有。.o 文件只包含当前源文件编译后的机器码和符号引用(比如对 std::cout、printf 的调用),但不包含头文件里函数的实现。那些实现留在标准库(如 libstdc++.so)或其它目标文件里,靠链接阶段解决。
这也是为什么单独运行 ./main.o 会提示 Permission denied 或 cannot execute binary file —— 它不是可执行格式,只是未解析依赖的中间产物。
立即学习“C++免费学习笔记(深入)”;
-
#include <iostream></iostream>在预处理阶段展开声明,不带实现 std::cout 在 <code>.o中记为未定义符号,链接时才绑定到 libstdc++- 如果用了自定义头文件(如
"utils.h"),且其实现写在utils.cpp里,那main.o也会标记对utils.cpp中函数的引用,需一起链接
为什么有时 g++ -c 会报错说找不到头文件?
不是头文件“不存在”,而是编译器找不到它的路径。默认只搜系统目录(如 /usr/include/c++/),如果你的头文件放在项目子目录(如 include/ 或 src/),必须显式加 -I 参数。
-
g++ -c src/main.cpp -Iinclude -Isrc→ 让预处理器在include/和src/下找#include - 路径顺序有影响:
-I越靠前优先级越高,可覆盖系统头文件(慎用) - 注意:
-I.表示当前目录,但不推荐,容易污染或引发歧义
生成的目标文件能跨平台复用吗?
不能。.o 是特定架构+ABI 的产物。x86_64 上生成的 main.o 无法拿去 ARM64 项目里链接,即使源码完全一样。
交叉编译时,必须用对应工具链的 g++,比如 arm-linux-gnueabihf-g++ -c main.cpp,生成的才是 ARM 兼容的 main.o。
- 同一架构下,不同 GCC 版本生成的
.o通常可互链,但启用-std=c++20或-fPIC等选项后需保持一致 -
.o不含调试信息,加-g才会嵌入 DWARF 数据,不影响二进制兼容性但增大体积


















