
🎬 个人主页:Vect个人主页 🎬 GitHub:Vect的代码仓库 🔥 个人专栏: 《数据结构与算法》《C++学习之旅》《Linux》
⛺️Per aspera ad astra.
// add.h
#pragma once
int add(int a, int b);// add.cpp
#include "add.h"
int add(int a, int b) { return a + b;}// main.cpp
#include <iostream>
#include "add.h"
int main(){
std::cout<<add(1,2)<<std::endl;
return 0;
}这里先提前有个认知:
Makefile是文件make是指令先来看代码,然后解读:
# 变量定义部分
SRC = main.cpp add.cpp
OBJ = $(SRC:.cpp=.o)
BIN = myapp
# 默认目标
$(BIN): $(OBJ)
g++ -o $@ $^
# 编译目标
%.o: %.cpp
g++ -c $< -o $@
# 清理目标
.PHONY: clean
clean:
rm -f $(OBJ) $(BIN)SRC = main.cpp add.cpp
.cpp的源文件SRC是一个包含需要编译的源文件的列表OBJ = $(SRC:.cpp=.o)
SRC中的.cpp全部转换成.o文件BIN = myapp
(BIN):(OBJ)
g++ -o @ ^
g++将.o文件链接成最终可执行文件myapp%.o: %.cpp
make如何将.cpp文件编译成.o文件%是通配符,代表一个任意的字符序列,这里表示会匹配所有的.cpp文件,将它们全部编译为对应的.o文件g++ -c &< -o $@
g++将.cpp文件编译成.o文件.PHONY: clean
clean是一个伪目标,而不是文件名make 会认为 clean 是一个任务,而不是文件,因此即使当前目录下存在名为 clean 的文件,make 也会执行 clean 规则的命令clean: rm -f (OBJ) (BIN)
clean 目标的命令部分,删除所有生成的目标文件和最终的可执行文件。.o和依赖关系main.o依赖于main.cppadd.o依赖于add.cpp在Makefile中,$OBJ 是要生成的目标文件,它的生成依赖于.cpp文件
make会从默认目标myapp开始,通过依赖关系逐步推导出需要做的工作
make看到myapp
myapp的形成依赖于main.o和add.o,make会从main.o和add.o开始推导
main.o
而main.o的生成又依赖于main.cpp,所以make会执行:g++ -c main.cpp -o main.o
add.o
同理add.o的生成依赖于add.cpp,所以make会执行: g++ -c add.cpp -o add.o
myapp
当生成了main.o和add.o,make会执行:g++ -o mayapp main.o add.o
推导是一个出栈入栈的过程
make开始时看到myapp,出栈myapp,处理它的依赖main.o和add.omain.o 和 add.o 处理完后,它们的目标文件会 入栈,然后 make 执行生成 myapp 的命令我们梳理清楚依赖链:
目标 | 直接依赖 | 构建规则 |
|---|---|---|
myapp | main.o add.o | g++ -o myapp main.o add.o |
main.o | main.cpp | g++ -c main.cpp -o main.o |
add.o | add.cpp | g++ -c add.cpp -o add.o |
clean | 伪目标 | rm -f main.o add.o myapp |

make在做依赖关系推导的时候,会用时间戳来决定哪些目标需要重新构建
时间戳的作用
make会比较每个目标文件和它的依赖文件的时间戳
make会重新构建目标文件make会跳过编译过程[vect@VM-0-11-centos make_file]$ stat main.cpp
File: ‘main.cpp’
Size: 102 Blocks: 8 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 1051720 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 1002/ vect) Gid: ( 1002/ vect)
Access: 2025-12-14 20:12:03.883557588 +0800
Modify: 2025-12-14 20:12:01.955499062 +0800
Change: 2025-12-14 20:12:01.955499062 +0800
Birth: -看一下三种时间:
Acesstime:访问时间,文件内容被读取/访问的时间Modifytime:修改时间,文件时间内容被修改的时间(文件大小、内容变化)Changetime:状态改变时间,文件**元数据(属性)**改变的时间(文件属性)过程演示:
第一次运行make
make的行为:
[vect@VM-0-11-centos make_file]$ make
g++ -c main.cpp -o main.o
g++ -c add.cpp -o add.o
g++ -o myapp main.o add.o此时目标文件和可执行文件都生成了,时间戳被记录
修改源文件并运行make
假设修改了 add.cpp 文件中的代码,例如:
int add(int a, int b) {
return a * b; // 修改了加法为乘法
}现在,make会根据文件时间戳决定是否重新编译:
main.o时间戳未变化,main.cpp不重新编译add.o文件的时间戳比add.cpp新,make会发现add.o的依赖文件add.cpp发生变化运行指令得到:
[vect@VM-0-11-centos make_file]$ make
g++ -c add.cpp -o add.o
g++ -o myapp main.o add.o不做任何修改,直接运行make
[vect@VM-0-11-centos make_file]$ make
make: `myapp' is up to date.总结:
.o)或依赖文件(.cpp)不存在,make 会强制编译并生成目标文件。
make 会重新编译依赖文件并更新目标文件。
make 会跳过编译过程,避免重复工作。

伪目标:没有对应文件的目标文件,用来执行命令而不关心文件的存在
伪目标不会检查时间戳,每次执行都会运行相关指令
.PHONY: clean
clean:
rm -f $(OBJ) $(BIN).PHONY 告诉 make clean 是伪目标,即使当前目录下有一个 clean 文件,make 也不会认为它是一个文件,而是会执行 rm 命令
程序发布方式:
在Linux下,gcc/g++默认生成的可执行程序是release版本,若想生成debug版本,就需要加上-g选项

对同一代码分贝生成release版本和debug版本的可执行程序,可以看到debug版本要更大,原因是debug版本包含了更多的调试信息
【进入gdb】
gdb 二进制文件名
【退出】
ctrl+d或quit调试命令
【常见命令】
list/l:列出源代码,从上次位置开始,每次列10行
list/l 函数名:列出指定函数的源代码
list/l 文件名:行号:列出指定文件的源代码
run/r:从程序开始连续执行

next/n:单步执行,不进入函数内部,相当于逐过程F10
step/s:单步执行,进入函数内部,相当于逐语句F11
break/b 文件名:行号:指定行号打断点,b 10 b test.c:10
info break/b:查看当前所有断点信息

这里显示断点编号和断点类型以及其他信息
finish:执行到当前函数返回,然后停止
print/p 表达式:打印表达式的值
p 变量:打印指定变量的值
set var 变量=值:修改变量的值
continue/c:从当前位置开始连续执行程序
delete/d breakpoints:删除所有断点
delete/d breakpoints n:删除序号为n的断点
disable breakpoints:禁用所有断点
enable breakpoints: 启用所有断点
info/i breakpoints:查看当前设置的断点列表
display 变量名:跟踪显示指定变量的值
undisplay 编号:取消对指定编号的变量的跟踪显示
until x:执行到指定行号
backtrace/bc:查看当前执行栈的各级函数调用及参数
info/i locals:查看当前栈帧的局部变量值
vim是一种多模式编辑器,总共有12种模式,本文只详细讲解三种常见模式:命令模式 插入模式 第行模式
vim file,如果文件不存在就会自动创建并进入vim编辑器页面,默认进入命令模式
shift+; 就是输入:
w:保存当前文件
wq:保存并退出
q!:不保存强制退出
n+yy:光标所在行开始,复制n行
n+p:从光标所在行下一行行首开始,粘贴n次
u:撤销上一次操作
ctrl+r:取消撤销
shift+g:即G,定位到文本末尾
gg:定位到文本开头
n+shift+g:定位到第n行
h j k l:← ↓ ↑ →移动光标
$:定位到本行末尾
^:定位到本行开头
w:光标跳到下一个字的开头
b:光标跳到上一个字的开头
n+x:光标所在位置开始向后删除n个字符
n+X:光标所在位置开始向前删除n个字符
dd:删除光标所在行
n+r+输入字符:从光标所在位置开始,用n个输入字符替换原字符
shift+~:光标所在位置大小写替换
进入底行模式之前,先按esc键确定在命令模式下,再按:进入第行模式
set nu:输入set nu,会在文件中每一行前面列出行号
set nonu:取消行号
/关键字:先按/,再输入想查找的内容,按n会跳转到下一个匹配的
?关键字:先按/,再输入想查找的内容,按n会跳转到上一个匹配的
w
q
q!
shift+r会进入替换模式,此时就可以进行文本、字符替换操作
ctrl+v会进入视图模式
hjkl会进行区域选择,按I进入插入模式,然后按输入//后立马按ESC回到命令模式,就可以实现批量注释
