前言
在 Linux 下学习 C / C++,一定绕不开两个编译命令:
gcc
和:
g++
很多初学者第一次接触 Linux 编译 C 语言程序时,可能会看到这样的命令:
gcc main.c
执行之后,当前目录下会生成一个文件:
a.out
这个 a.out 就是编译生成的可执行程序。
运行它:
./a.out
如果程序没有问题,就可以看到程序的运行结果。
但是很多人刚开始学习时,会对这些问题感到疑惑:
gcc 是什么?
g++ 又是什么?
gcc main.c 为什么会生成 a.out?
a.out 是什么?
为什么运行程序要写 ./a.out?
gcc -o main main.c 是什么意思?
-o 后面的 main 是输入文件还是输出文件?
gcc 编译程序时到底经历了哪些步骤?
什么是预处理、编译、汇编、链接?
为什么有时候会出现 undefined reference?
为什么找不到头文件?
本文就从最简单的 gcc main.c 开始,按照从浅到深、从简单到复杂的顺序,带你完整理解 Linux 下 gcc / g++ 从源代码到可执行程序的整个过程。
一、gcc 和 g++ 是什么?
1. gcc 是什么?
gcc 原本表示 GNU C Compiler,也就是 GNU C 语言编译器。
现在的 gcc 通常指 GNU Compiler Collection,也就是 GNU 编译器套件。
它不仅可以编译 C 语言,也可以支持 C++、Objective-C、Fortran 等多种语言。
不过在刚开始学习时,可以先简单理解为:
gcc 主要用于编译 C 语言程序
例如有一个 C 源文件:
main.c
就可以使用:
gcc main.c
来编译它。
2. g++ 是什么?
g++ 是 GNU C++ 编译器,主要用于编译 C++ 程序。
例如有一个 C++ 源文件:
main.cpp
就可以使用:
g++ main.cpp
来编译它。
3. gcc 和 g++ 的区别
简单记忆:
.c 文件一般使用 gcc 编译
.cpp 文件一般使用 g++ 编译
例如:
gcc main.c
用于编译 C 程序。
g++ main.cpp
用于编译 C++ 程序。
对于 C++ 程序,建议使用 g++,因为 g++ 会自动按照 C++ 的方式进行编译和链接,并且会自动链接 C++ 标准库。
例如下面这个 C++ 程序:
#include <iostream>
using namespace std;
int main()
{
cout << "Hello C++" << endl;
return 0;
}
推荐使用:
g++ main.cpp
如果使用:
gcc main.cpp
可能会出现类似下面的链接错误:
undefined reference to `std::cout'
undefined reference to `std::endl'
原因是 gcc 默认不会像 g++ 那样自动链接 C++ 标准库。
所以初学阶段可以先记住一句话:
写 C 用 gcc,写 C++ 用 g++。
二、从最简单的命令开始:gcc main.c
先准备一个最简单的 C 程序。
文件名:
main.c
代码内容如下:
#include <stdio.h>
int main()
{
printf("Hello gcc\n");
return 0;
}
现在使用 gcc 编译:
gcc main.c
这条命令的意思是:
使用 gcc 编译 main.c 这个源文件
执行完成后,查看当前目录:
ls
可以看到类似结果:
a.out main.c
可以发现,执行 gcc main.c 之后,系统生成了一个新的文件:
a.out
这个 a.out 就是编译出来的可执行程序。
运行它:
./a.out
输出结果:
Hello gcc
三、为什么生成的文件叫 a.out?
当我们执行:
gcc main.c
时,只告诉了 gcc 一件事情:
我要编译 main.c
但是我们没有告诉 gcc:
最终生成的可执行文件叫什么名字
所以 gcc 会使用默认的输出文件名:
a.out
也就是说:
gcc main.c
可以理解为:
编译 main.c,并默认生成名为 a.out 的可执行文件
a.out 是 Unix / Linux 系统中比较传统的默认可执行文件名。
四、为什么运行程序要写 ./a.out?
在 Windows 中,我们可能习惯双击运行程序。
但是在 Linux 命令行中,要运行当前目录下的程序,通常需要写:
./程序名
所以运行 a.out 时,需要写:
./a.out
这里的:
. 表示当前目录
/ 表示路径分隔符
所以:
./a.out
表示:
运行当前目录下的 a.out 文件
如果直接输入:
a.out
可能会提示:
command not found
原因是 Linux 默认不会直接从当前目录查找可执行程序。
五、使用 -o 指定输出文件名
每次编译都生成 a.out 并不方便。
例如我们希望生成的可执行文件名叫:
main
就可以使用 -o 参数。
命令如下:
gcc -o main main.c
这条命令的意思是:
使用 gcc 编译 main.c,并把生成的可执行文件命名为 main
其中:
-o main
表示:
指定输出文件名为 main
后面的:
main.c
表示:
输入的源文件是 main.c
执行后查看当前目录:
ls
可以看到:
main main.c
运行程序:
./main
输出:
Hello gcc
六、一定要理解:-o 后面跟的是输出文件名
-o 是 gcc / g++ 中非常常用的参数,它的作用是指定输出文件名。
例如:
gcc -o main main.c
可以拆开理解为:
gcc 使用 gcc 编译器
-o main 指定输出文件名为 main
main.c 输入源文件是 main.c
这里一定要注意:
-o 后面的 main 是输出文件名,不是源文件名。
所以,下面这种写法是非常危险的:
gcc -o main.c main.c
这条命令的意思不是"编译 main.c"。
它的真实含义是:
把 main.c 编译后的结果输出成 main.c
也就是说,输出文件名和源文件名重名了。
这样可能会导致原来的 main.c 源代码被覆盖成一个二进制可执行文件。
此时看起来就像:
源文件被删了
但更准确地说,是:
源文件被编译生成的二进制文件覆盖了
所以一定要记住:
不要把 -o 后面的输出文件名写成已有的源文件名。
正确写法:
gcc -o main main.c
错误且危险的写法:
gcc -o main.c main.c
七、gcc -o main main.c 和 gcc main.c -o main 的区别
下面两种写法都可以:
gcc -o main main.c
也可以写成:
gcc main.c -o main
它们的作用是一样的,都是:
编译 main.c,并生成名为 main 的可执行文件
但是对于初学者来说,更推荐先使用:
gcc -o main main.c
因为这种写法更容易理解:
gcc 编译器
-o main 输出文件名
main.c 输入源文件
而:
gcc main.c -o main
虽然也正确,但是初学者容易把 main.c 和 main 的关系看混。
所以本文后续主要采用:
gcc -o main main.c
作为示例。
八、gcc 常见命令格式
gcc 最基础的使用格式是:
gcc 源文件
例如:
gcc main.c
表示:
编译 main.c,默认生成 a.out
如果想指定输出文件名,可以写成:
gcc -o 输出文件名 源文件
例如:
gcc -o main main.c
表示:
编译 main.c,生成可执行文件 main
多个源文件也可以一起编译:
gcc -o main main.c add.c
表示:
编译 main.c 和 add.c,最后生成可执行文件 main
九、gcc main.c 背后到底做了什么?
虽然我们只执行了一条命令:
gcc main.c
但是 gcc 在背后并不是只做了一件事。
它实际上完成了四个主要阶段:
预处理 -> 编译 -> 汇编 -> 链接
完整过程可以理解为:
main.c
↓ 预处理
main.i
↓ 编译
main.s
↓ 汇编
main.o
↓ 链接
a.out
如果指定输出文件名:
gcc -o main main.c
那么最终生成的就是:
main
整体过程就是:
main.c
↓ 预处理
main.i
↓ 编译
main.s
↓ 汇编
main.o
↓ 链接
main
简单来说:
gcc main.c
或者:
gcc -o main main.c
这一条命令背后其实自动完成了:
预处理 + 编译 + 汇编 + 链接
下面我们一步一步拆开来看。
十、第一步:预处理
预处理是整个编译过程的第一步。
可以使用 -E 参数让 gcc 只执行预处理:
gcc -E main.c -o main.i
这条命令的意思是:
只对 main.c 进行预处理,并把结果输出到 main.i
预处理阶段主要做这些事情:
1. 展开头文件
2. 替换宏定义
3. 处理条件编译
4. 删除注释
例如有这样一段代码:
#include <stdio.h>
#define MESSAGE "Hello gcc"
int main()
{
printf("%s\n", MESSAGE);
return 0;
}
其中:
#include <stdio.h>
会在预处理阶段被展开。
宏定义:
#define MESSAGE "Hello gcc"
会被替换。
所以:
printf("%s\n", MESSAGE);
经过预处理后,大致会变成:
printf("%s\n", "Hello gcc");
预处理之后生成的文件通常使用 .i 后缀:
main.i
这个文件依然是 C 代码,只是已经完成了头文件展开、宏替换、条件编译处理等工作。
十一、第二步:编译
编译阶段会把预处理后的 C 代码转换成汇编代码。
可以使用 -S 参数让 gcc 只编译到汇编阶段:
gcc -S main.i -o main.s
也可以直接从 C 源文件生成汇编文件:
gcc -S main.c -o main.s
执行后会生成:
main.s
.s 文件里面是汇编代码。
内容可能类似这样:
.file "main.c"
.text
.globl main
.type main, @function
main:
pushq %rbp
movq %rsp, %rbp
汇编代码已经比 C 语言更接近 CPU 能理解的指令了。
但是它仍然不是最终可以直接运行的程序。
十二、第三步:汇编
汇编阶段会把汇编代码转换成目标文件。
可以使用 -c 参数生成目标文件:
gcc -c main.s -o main.o
也可以直接从 C 源文件生成目标文件:
gcc -c main.c -o main.o
执行后会生成:
main.o
.o 文件叫做目标文件,也叫 object file。
它已经包含了机器指令,但是还不能直接运行。
例如你不能直接这样运行:
./main.o
因为 main.o 只是一个中间文件,还没有完成最后的链接。
十三、第四步:链接
链接是生成最终可执行程序的最后一步。
如果已经有了目标文件:
main.o
可以使用下面的命令进行链接:
gcc -o main main.o
这条命令表示:
把 main.o 链接成最终可执行文件 main
执行后生成:
main
运行:
./main
输出:
Hello gcc
链接阶段主要做这些事情:
1. 合并多个目标文件
2. 解析函数和变量的引用关系
3. 链接标准库或第三方库
4. 生成最终可执行文件
例如程序中使用了:
printf("Hello gcc\n");
但是 printf 的真正实现并不在我们自己写的 main.c 里面,而是在 C 标准库中。
在链接阶段,链接器会找到 printf 的实现,并把它和我们的程序关联起来,最终生成可以运行的可执行文件。
十四、完整分步骤编译过程
原本一条命令:
gcc -o main main.c
可以拆成下面四步:
# 1. 预处理:main.c -> main.i
gcc -E main.c -o main.i
# 2. 编译:main.i -> main.s
gcc -S main.i -o main.s
# 3. 汇编:main.s -> main.o
gcc -c main.s -o main.o
# 4. 链接:main.o -> main
gcc -o main main.o
最终运行:
./main
输出:
Hello gcc
也就是说:
gcc -o main main.c
等价于 gcc 帮我们自动完成了:
预处理 main.c 生成 main.i
编译 main.i 生成 main.s
汇编 main.s 生成 main.o
链接 main.o 生成 main
平时我们通常不需要手动拆开这四步,因为 gcc 会自动完成。
但是理解这四步非常重要,因为很多编译错误、链接错误都和这些阶段有关。
十五、C++ 程序的编译过程
C++ 程序的编译过程和 C 程序类似,也分为:
预处理 -> 编译 -> 汇编 -> 链接
假设有一个 C++ 文件:
main.cpp
代码如下:
#include <iostream>
using namespace std;
int main()
{
cout << "Hello g++" << endl;
return 0;
}
最简单的编译方式:
g++ main.cpp
默认也会生成:
a.out
运行:
./a.out
输出:
Hello g++
如果想指定输出文件名:
g++ -o main main.cpp
运行:
./main
输出:
Hello g++
C++ 也可以分步骤编译:
# 1. 预处理:main.cpp -> main.ii
g++ -E main.cpp -o main.ii
# 2. 编译:main.ii -> main.s
g++ -S main.ii -o main.s
# 3. 汇编:main.s -> main.o
g++ -c main.s -o main.o
# 4. 链接:main.o -> main
g++ -o main main.o
C++ 预处理后的文件通常可以使用:
.ii
作为后缀。
C 语言预处理后的文件通常使用:
.i
作为后缀。
十六、头文件和源文件的关系
很多初学者会把头文件和源文件混在一起。
先看一个简单例子。
项目结构如下:
project/
├── add.h
├── add.c
└── main.c
add.h 内容如下:
#ifndef ADD_H
#define ADD_H
int add(int a, int b);
#endif
add.c 内容如下:
#include "add.h"
int add(int a, int b)
{
return a + b;
}
main.c 内容如下:
#include <stdio.h>
#include "add.h"
int main()
{
int ret = add(10, 20);
printf("ret = %d\n", ret);
return 0;
}
其中:
int add(int a, int b);
是函数声明。
它的作用是告诉编译器:
有一个函数叫 add
它接收两个 int 参数
它返回一个 int 类型的结果
但是这只是声明,不是实现。
真正的实现是在 add.c 里面:
int add(int a, int b)
{
return a + b;
}
所以可以简单理解为:
头文件 .h:主要放声明
源文件 .c:主要放实现
十七、多文件直接编译
对于上面的项目,可以直接这样编译:
gcc -o main main.c add.c
这条命令的意思是:
同时编译 main.c 和 add.c,并链接生成可执行文件 main
运行:
./main
输出:
ret = 30
如果只编译:
gcc -o main main.c
可能会出现:
undefined reference to `add'
原因是 main.c 里面调用了 add 函数,但是 add 函数的实现写在 add.c 里面。
如果编译命令中没有带上 add.c,链接器就找不到 add 的实现。
所以正确写法是:
gcc -o main main.c add.c
十八、多文件分步编译
大型项目中,通常不会每次都把所有 .c 文件从头编译一遍。
更常见的方式是先分别生成 .o 目标文件,再统一链接。
例如:
gcc -c main.c -o main.o
gcc -c add.c -o add.o
这两条命令分别生成:
main.o
add.o
然后再链接:
gcc -o main main.o add.o
运行:
./main
输出:
ret = 30
这种方式的好处是:
如果只修改了 add.c,只需要重新编译 add.c
不需要重新编译 main.c
最后重新链接即可
例如:
gcc -c add.c -o add.o
gcc -o main main.o add.o
这也是 Makefile 和大型项目构建系统的基础。
十九、头文件路径:-I
如果头文件不在当前目录,而是在单独的 include 目录中,就需要使用 -I 参数指定头文件搜索路径。
例如项目结构如下:
project/
├── include/
│ └── add.h
└── src/
├── add.c
└── main.c
此时 main.c 中可能这样写:
#include "add.h"
但是编译时如果直接写:
gcc -o main src/main.c src/add.c
可能会报错:
fatal error: add.h: No such file or directory
意思是:
找不到 add.h 这个头文件
这时候需要告诉 gcc 去哪里找头文件:
gcc -o main src/main.c src/add.c -I include
其中:
-I include
表示:
把 include 目录加入头文件搜索路径
也可以写成:
gcc -I include -o main src/main.c src/add.c
-I 的位置一般比较灵活,但要保证路径写正确。
二十、库文件是什么?
头文件只提供声明,真正的函数实现可能来自源文件,也可能来自库文件。
库文件可以简单理解为:
已经提前编译好的代码集合
Linux 下常见库文件有两类:
静态库:.a
动态库:.so
例如:
libm.a
libm.so
libpthread.so
头文件和库文件的区别可以这样理解:
头文件:告诉编译器函数长什么样
库文件:告诉链接器函数真正在哪里
例如:
#include <math.h>
math.h 只是提供数学函数的声明。
而数学函数真正的实现,需要在链接阶段链接数学库。
二十一、链接库:-L 和 -l
编译程序时,如果需要链接第三方库,常见参数有两个:
-L:指定库文件所在目录
-l:指定要链接的库名
例如:
gcc -o main main.c -L ./lib -lxxx
其中:
-L ./lib
表示:
到 ./lib 目录下查找库文件
而:
-lxxx
表示:
链接名为 xxx 的库
这里要注意,-lxxx 并不是去找一个叫 xxx 的文件。
它实际会去找类似这样的库文件:
libxxx.so
libxxx.a
也就是说:
-lm
实际对应的可能是:
libm.so
libm.a
-lpthread
实际对应的可能是:
libpthread.so
libpthread.a
二十二、数学库示例:-lm
看下面这个程序:
#include <stdio.h>
#include <math.h>
int main()
{
double ret = sqrt(16.0);
printf("%f\n", ret);
return 0;
}
文件名:
main.c
如果直接编译:
gcc -o main main.c
在一些环境下可能会出现链接错误:
undefined reference to `sqrt'
原因是:
sqrt 函数的声明在 math.h 中
但 sqrt 函数的实现需要链接数学库 libm
正确写法:
gcc -o main main.c -lm
其中:
-lm
表示链接数学库。
需要注意,库参数通常建议放在源文件或目标文件后面。
推荐:
gcc -o main main.c -lm
不推荐:
gcc -lm -o main main.c
因为在某些链接器规则下,库的顺序会影响符号解析。
二十三、编译错误和链接错误的区别
学习 gcc / g++ 时,一定要区分:
编译错误
链接错误
1. 编译错误
编译错误通常发生在源代码变成目标文件之前。
常见原因有:
语法错误
变量未声明
类型错误
找不到头文件
函数声明不匹配
例如:
#include "add.h"
但是编译器找不到 add.h,就会出现:
fatal error: add.h: No such file or directory
这是编译阶段的问题。
2. 链接错误
链接错误通常发生在 .o 目标文件生成之后,链接成可执行文件的时候。
常见错误:
undefined reference to `xxx'
例如:
undefined reference to `add'
这说明:
编译器知道 add 这个函数存在声明
但是链接器找不到 add 函数的真正实现
比如只写了:
gcc -o main main.c
但是没有把 add.c 一起编译进去,就可能出现这个错误。
正确写法:
gcc -o main main.c add.c
或者:
gcc -c main.c -o main.o
gcc -c add.c -o add.o
gcc -o main main.o add.o
二十四、常见 gcc 参数总结
1. -o:指定输出文件名
gcc -o main main.c
表示:
编译 main.c,生成可执行文件 main
不要写成:
gcc -o main.c main.c
因为这样可能会覆盖源文件。
2. -E:只进行预处理
gcc -E main.c -o main.i
表示:
只进行预处理,不编译、不汇编、不链接
3. -S:只生成汇编文件
gcc -S main.c -o main.s
表示:
生成汇编文件 main.s
4. -c:只生成目标文件
gcc -c main.c -o main.o
表示:
生成目标文件 main.o,不进行链接
5. -I:指定头文件搜索路径
gcc -I include -o main src/main.c src/add.c
表示:
让 gcc 到 include 目录下查找头文件
6. -L:指定库文件搜索路径
gcc -o main main.c -L ./lib -lxxx
表示:
让链接器到 ./lib 目录下查找库文件
7. -l:指定链接库
gcc -o main main.c -lm
表示:
链接数学库 libm
8. -Wall:开启常见警告
gcc -Wall -o main main.c
表示:
开启常见编译警告
建议平时写代码时加上。
9. -Wextra:开启更多警告
gcc -Wall -Wextra -o main main.c
表示:
在 -Wall 的基础上开启更多警告
10. -g:生成调试信息
gcc -g -o main main.c
表示:
生成调试信息,方便使用 gdb 调试
例如:
gdb ./main
11. -O:开启优化
常见优化等级:
-O0
-O1
-O2
-O3
开发调试阶段常用:
gcc -g -O0 -o main main.c
发布程序时可以使用:
gcc -O2 -o main main.c
12. -std:指定语言标准
C 语言示例:
gcc -std=c11 -o main main.c
C++ 示例:
g++ -std=c++17 -o main main.cpp
常见 C++ 标准:
c++11
c++14
c++17
c++20
c++23
二十五、gcc 常用命令总结
# 编译 C 程序,默认生成 a.out
gcc main.c
# 运行默认生成的程序
./a.out
# 指定输出文件名
gcc -o main main.c
# 运行指定名称的程序
./main
# 开启常见警告
gcc -Wall -o main main.c
# 开启更多警告
gcc -Wall -Wextra -o main main.c
# 生成调试版本
gcc -g -O0 -o main main.c
# 生成优化版本
gcc -O2 -o main main.c
# 指定 C 标准
gcc -std=c11 -o main main.c
# 只预处理
gcc -E main.c -o main.i
# 只生成汇编
gcc -S main.c -o main.s
# 只生成目标文件
gcc -c main.c -o main.o
# 根据目标文件链接生成可执行文件
gcc -o main main.o
# 多文件直接编译
gcc -o main main.c add.c
# 多文件分步编译
gcc -c main.c -o main.o
gcc -c add.c -o add.o
gcc -o main main.o add.o
# 指定头文件路径
gcc -I include -o main src/main.c src/add.c
# 指定库路径并链接库
gcc -o main main.c -L ./lib -lxxx
# 链接数学库
gcc -o main main.c -lm
二十六、g++ 常用命令总结
# 编译 C++ 程序,默认生成 a.out
g++ main.cpp
# 运行默认生成的程序
./a.out
# 指定输出文件名
g++ -o main main.cpp
# 运行指定名称的程序
./main
# 开启常见警告
g++ -Wall -o main main.cpp
# 开启更多警告
g++ -Wall -Wextra -o main main.cpp
# 生成调试版本
g++ -g -O0 -o main main.cpp
# 生成优化版本
g++ -O2 -o main main.cpp
# 指定 C++ 标准
g++ -std=c++17 -o main main.cpp
# 只预处理
g++ -E main.cpp -o main.ii
# 只生成汇编
g++ -S main.cpp -o main.s
# 只生成目标文件
g++ -c main.cpp -o main.o
# 根据目标文件链接生成可执行文件
g++ -o main main.o
# 多文件直接编译
g++ -o main main.cpp add.cpp
# 多文件分步编译
g++ -c main.cpp -o main.o
g++ -c add.cpp -o add.o
g++ -o main main.o add.o
# 指定头文件路径
g++ -I include -o main src/main.cpp src/add.cpp
# 指定库路径并链接库
g++ -o main main.cpp -L ./lib -lxxx
二十七、推荐的编译命令
对于 C 语言学习阶段,推荐使用:
gcc -Wall -Wextra -g -O0 -o main main.c
含义:
-Wall 开启常见警告
-Wextra 开启更多警告
-g 生成调试信息
-O0 不进行优化,方便调试
-o main 输出文件名为 main
main.c 输入源文件
对于 C++ 学习阶段,推荐使用:
g++ -std=c++17 -Wall -Wextra -g -O0 -o main main.cpp
含义:
-std=c++17 指定 C++17 标准
-Wall 开启常见警告
-Wextra 开启更多警告
-g 生成调试信息
-O0 不进行优化,方便调试
-o main 输出文件名为 main
main.cpp 输入源文件
发布程序时可以使用优化选项:
gcc -O2 -o main main.c
或者:
g++ -std=c++17 -O2 -o main main.cpp
二十八、几个核心概念总结
1. gcc main.c 会默认生成 a.out
gcc main.c
默认生成:
a.out
运行:
./a.out
2. 使用 -o 可以指定输出文件名
gcc -o main main.c
表示:
编译 main.c,生成 main
3. -o 后面是输出文件名
一定不要写成:
gcc -o main.c main.c
因为这样可能会把源文件 main.c 覆盖掉。
4. 一条 gcc 命令背后有四个阶段
预处理 -> 编译 -> 汇编 -> 链接
对应文件变化:
main.c -> main.i -> main.s -> main.o -> main
5. 头文件不是库文件
头文件主要放声明:
函数声明
宏定义
类型定义
结构体声明
类声明
库文件或源文件中才有真正的实现。
6. 编译错误和链接错误不是一回事
编译错误常见于:
语法错误
找不到头文件
类型错误
声明错误
链接错误常见于:
undefined reference
找不到函数实现
找不到库文件
7. C 用 gcc,C++ 用 g++
gcc -o main main.c
用于 C 程序。
g++ -o main main.cpp
用于 C++ 程序。
结语
刚开始学习 Linux 下 C / C++ 编译时,不要一上来就死记复杂命令。
可以先从最简单的命令开始:
gcc main.c
理解它会默认生成:
a.out
然后再学习如何指定输出文件名:
gcc -o main main.c
接着再逐步理解这条命令背后的完整过程:
main.c
↓ 预处理
main.i
↓ 编译
main.s
↓ 汇编
main.o
↓ 链接
main
当你理解了:
预处理
编译
汇编
链接
这四个阶段之后,再看 Makefile、多文件编译、静态库、动态库、头文件路径、库文件链接等内容,就会清晰很多。
最终需要记住的核心命令是:
gcc main.c
默认生成:
a.out
指定输出文件名:
gcc -o main main.c
C++ 程序:
g++ -o main main.cpp
理解这些基础内容,是继续学习 Linux C / C++ 开发、Makefile、CMake、静态库、动态库以及大型项目构建的第一步。