码海拾遗

前言：完整的总结总是劳神耗时的，已经熟稔的或者易于得到的部分也没有总结下来的必要。然遨游码海，总归有一些需要记忆的小点，好记性不如烂笔头，单开一篇又没必要，索性全归为一篇，作为手册。

随着越拾越多，大口袋又分成了若干小口袋，分别是【语言探幽】【底层探幽】【配置万千】，分别记录一些各语言知识点、四大件的内容以及有关环境搭建配置的内容。而本文【码海拾遗】主要记录一些命令、工具的使用。或许可以叫工具手册，但为了纪念这一创举，保留了 “码海拾遗” 的名字

1 linux

1.1 命令

diff

diff file1 file2：比较文件的异同：怎么样改变第一个文件，可以把它变成第二个文件

< 表示左边 file1 独有的文件 / 行，>表示右边 file2 独有的文件 / 行，| 表示两边都有，但不一样

2,4a2,4：数字是闭区间，[2-4]行，需要add 才能跟 file2 一样，【add、 change、 delete】

diff file1 file2 -y -W 100 | grep ">"：并排显示不同之处，每排宽度 100

-y并排显示： --suppress-common-lines仅显示不同的；--left-column相同的仅在左边显示

-w忽略所有空格，-i忽略大小写，-I <str>忽略字符串，-b 忽略行尾空格，字符串中若干空格视为相等

-C <num> 不同之处上下显示 num 行上下文

-q仅显示是否相同

-p可用于比较 C 程序

-r递归比较子目录，-N独有的文件会显示 "only in xxx"

diff {dir1} {dir2} -Nrqy只显示文件夹中哪些文件不一样，不输出具体的文件

find

find . -perm /111 -type f -delete：linux 下删除可执行文件（加个 type 可以略掉文件夹）（find 命令参考）

-perm mode：必须与 mode 指示的一样
-perm /mode：mode 中表示的，满足一个就好了，比如111，则只要有一个1满足就好了
-perm -mode：mode 中表示的，必须全部具有，111就是 ugo 都得可执行，缺一不可。别的属性不管

find -iname readme -o -name *.c -not -size +100k -exec ls -i {} + -fprintf0 file.txt ：
find 查找是完全匹配；逻辑与或非；size 的单位注意默认不是 byte；exec 结尾是{} +大括号表示结果

grep

-i：忽略大小写进行匹配

-v：反向查找，只打印不匹配的行

-E: 使用正经的正则表达式

-n：显示匹配行的行号

-r：递归查找子目录中的文件

-l：只打印匹配的文件名（小写 L）

-c只打印匹配的行数

sed

sed 命令的基本格式是sed [-ni][-e ][-f<script文件>][文本文件]

-n：安静模式，只显示被 sed 处理过的行（否则会输出所有来自 stdin 的输入）

-e：允许后面直接跟命令，换句话说，不使用 -e 的话命令需要用单引号括起来。可以使用多个 -e

-f：允许使用指定 sed 脚本文件

-i：直接处理文件本身（会生成 temp 文件）

sed 命令中有一些动作：（sed 从 1 开始计算行）

i \：插入， 后面接字串，插入在当前行的上一行 *（注意 i a c 这三个动作后面要加上反斜杠）*

a\：新增， 后面接字串，插入在当前行的下一行

c\ ：取代， 后面接字串，取代 n1, n2 之间的行

d ：删除，因为是删除，所以 d 后面通常不接任何东西

p ：打印，亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行

s ：取代，通常搭配正则表达式，例如 1,20s/old/new/g

sed 以行为单位处理，加g是替换全部 pattern，不加是只替换每一行的第一个

Copy
# 在第二行上面插入一行 rowxxxyyyy
sed -i -e 2i\ rowxxxyyyy test.txt
sed '2,5c\ shuaikai'
# 在满足 pattern 模式的行下面插入一行
sed -i '/.*123.*/a 456' test.txt
# 可以用圆括号来进行正则表达式捕获，并用\+数字来进行引用。圆括号要进行转义
echo "Hello, World" | sed -n 's#.*,\s\(\w*\)#\1#p'

awk

awk 命令的基本格式是awk -F " " ' pattern { action } ' filename，即指定分隔符，然后单引号括起来的所有内容作为参数传递给 awk，其中前半部分是一个正则表达式 / 条件，后面具体执行的操作用大括号括起来

awk 处理文件是以行为单位，对每一行执行操作；每一行通过分隔符划分为NF个部分

NR：当前处理的行号；NF：当前行的块数。NF==0即表示空行

$0：整行内容；$1...：第 1、2...NR 部分

使用变量不需要声明，第一次用到的时候自动赋空值

循环、分支等与 C 语言相同

action 部分可执行内置函数：print、length、sqrt、match等，也可以通过system()来执行任意函数

BEGIN块，指定在执行动作之前做什么；EDN块，指定在执行完动作之后做什么

Copy
# 输出csv文件每行中长度超过5的字符串，不超过的用xxx代替
awk -F ',' 'NF%3==0 {for(i=1;i<=NF;i++) if(length($i)>5) print$i; else if print"xxx"}'
# 删除文件中行号是4的倍数的行
awk 'NR%4==0 {print NR}' file | xargs -I{} sed -i "{}d" file
# BAEGIN 和 END 的示意，中间的action才是真正要执行的命令
## 比如如果需要什么累加的东西，则可以在 END 块中输出出来
awk '[pattern] BAEGIN{print"我要开始了"} {action...} END{print"我结束了"}'

例子

例 1 == 用 awk 和 sed 迁移阿里云上的图片：==

找到阿里云 oss 仓库，选择批量导出 url，导出后是一个.csv 文件，格式为 obj，url

找一个文件夹下载所有 url

Copy
cat export_urls.csv | awk -F, '{print $2}' | xargs wget

把下载的这些文件上传到新的 oss 上，得到新的链接。这会导致原来的笔记里面的图片链接全部失效，因此要更改链接。链接的区别只在前面的 bucket 地址，后面的图片名是完全一样的。因此只需要找到所有的笔记文件，把其中图片 url 中前面的 bucket 链接改成新的连接前缀即可

此处用到的 fd 命令要先下载，即 fd-find。可以对文件夹进行递归正则查询。至此，就完成了对所有图片的迁移、更改链接操作。

Copy
fd ".*\.md$" | xargs sed -i 's#https:\/\/xxx.xxx#https:\/\/yyy.yyy#g'

1.2 工具

直接：sudo apt install

tldr：too long dont read，一个简单版本的 man 手册，记得先 - u 更新一下

fzf：对输出列表进行模糊查询

colordiff：彩色版 diff，可以 alias 为 diff

fd-find：更快的 find 命令，命令为fdfind，alias 为 fd，功能非常多，-h查看

htop：更易于阅读的 top 命令

ncdu：更易于阅读的 du 命令，可以直接排序，查看文件夹大小

ripgrep：更强大的 grep 命令，命令为rg

bat：能高亮的 cat 命令，命令为batcat，alias 为 bat

diff-so-fancy：下载后添加到 PATH，chown 和 chgrp 一下就好了，用法是git diff --color | diff-so-fancy，可以 alias 为 gitd。能够让 git diff 显示的清晰一些，看情况用

manpages-zh：中文 man 手册，用法：man -M /usr/share/man/zh_CN，alias 为cman
manpages-posix-dev：POSIX 的 man 手册

注意，vscode 中有时不能识别一些函数如sigaction、pthread_xxx等，是因为没有 "定义"__USE_POSIX这个宏（但实际上运行的时候是定义的），想要看补全的话，可以手动在，比如 signal.h 头文件前面 define 上

听说 c_cpp_properties.json中定义"__USE_POSIX=1",也行，但我的不行。但这不失为定义宏的好地方

cgdb：可以随时预览代码的调试。⛓命令参考 / Esc (vim) i (cgdb) s (cgdb 翻页)

Copy
#可能会缺少 curses.h 文件，可以先
sudo apt install libncurses5-dev libncursesw5-dev
#安装脚本：
wget https://shuaikai-bucket0001.oss-cn-shanghai.aliyuncs.com/config/gdb/installCgdb.sh
# mkdir ~/.cgdb
wget -O ~/.cgdb/cgdbrc https://shuaikai-bucket0001.oss-cn-shanghai.aliyuncs.com/config/gdb/cgdbrc
wget -O ~/.gdbinit https://shuaikai-bucket0001.oss-cn-shanghai.aliyuncs.com/config/gdb/.gdbinit

expect：交互的终端脚本工具，可以编写一些期待输入的脚本，expect xxx send xxx

neofetch：用于显示系统信息以及一个 ASCII-logo，挺好看的

其他非必要：

ossutil：阿里云对象存储的命令行工具

Copy
#(1) 下载安装
wget https://gosspublic.alicdn.com/ossutil/install.sh && sudo bash install.sh && rm install.sh
#(2) 生成配置文件 连按几下回车即可
ossutil config
#(3) 下载自定义配置文件
wget -O .ossutilconfig https://shuaikai-bucket0001.oss-cn-shanghai.aliyuncs.com/config/others/.ossutilconfig
wget -O .bash_aliases https://shuaikai-bucket0001.oss-cn-shanghai.aliyuncs.com/config/bash/.bash_aliases

man cpp：cpp 的 man 手册，包括一些浏览器检索的办法 🔗 Linux 自主安装 C++man 手册

1.3 终端操作

ctrl-a/e: 行首 / 行尾； Alt-b/f: 左 / 右一个单词
crtl-w: 往左删一个词； Alt-d: 往右删一个词
ctrl-u/k: 删除光标左 / 右所有字符
ctrl-y: 粘贴刚才删除的内容
ctrl shift '-': 撤销操作

^xxx: 删除上一条命令中的 xxx
^foo^bar: 把上一条命令中的 foo 替换为 bar

>：把程序的标准输出重定向
2>：把程序的标准错误重定向
&> /dev/null：把程序的标准输出和标准错误都重定向到 null，这样啥都看不到了

2 GCC

版本切换

Copy
# 先安装不同版本的 gcc。只需指定大版本就好，小版本好像会找不到
sudo apt install gcc-8
sudo apt install gcc-11
# “注册”到一个能切换的地方。后面的数字是【权值】，不指定的时候默认使用权值最大的版本
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 800
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 1100
# 进行版本切换
sudo update-alternatives --config gcc

3 GDB

命令

通用命令

:book:GDB Reference 🔗调试器 GDB 常用功能

x / [Length][Format: t o d x f a c s] [Address expression b-8 h-16 w-32 g-64\ ] 📎GDB Command Reference

**p/**t-2 o-8 d-10 x-16 f-loat a-ddress c-har s-tring [var]

⚠️ 要注意区分，x 是扫描内存，因此后面跟的直接是内存地址， 而 p 是输出变量的值，因此后面想跟地址的话，需要取其内容，即加上*

关于 *，很多命令地址前面都要加星号，因为不加星号的一个地址，是被当成函数来看待的

s n ：C 语言级别的单步执行； **si ni** 汇编级别的单步执行

i [line] / [locals] / [vtbl] / [args] / [checkpoints] / [breakpoints]

info line [line] / [function] / [*addr]：显示源码对应的内存中的起始结束地址

info vtbl [objs]：直接查看对象的虚函数表（也可以类型转换的形式打印出来，参考C++ 类的内存分配，基本思想就是：对象的第一块内存放的就是虚表，虚表是一个函数指针数组，因此可以先将对象地址转换为指向指针的指针，然后对其取内容，就得到了虚表指针。把这个值转换为指向指针的指针，即得虚表）

set print array-indexes on：打印数组的时候显示 index

set disassemble next-line on，disassemble

set [args] / [register] / [*address] = [val]：设置参数、寄存器值、内存处值

jump [*address]：跳转到指定地址处执行，return [val]：直接返回。都可以改变程序走向。

shell [cmd]：运行 shell 命令

rbreak [regex]：在所有满足正则表达式的函数处打断点

多进程 / 线程调试

gdb [pid]：调试正在运行的进程，或者进去后 attch [pip]

例子

打印栈内容（你打数组肯定也行）：不妨设 $rsp 中存放的是 0x1234 p $rsp => (void*)0x1234

x/10dw $rsp 或 x/10dw 0x1234，即用 x 命令直接把栈那一块内存扫描出来

p *(int (*)[10])0x1234 把栈顶地址类型转换为一个指向数组的指针，然后 print 这个数组 val 的值（所以要加*），即栈的内容

p (int [10])*0x1234 把栈顶的内容直接变成一个数组，然后输出

p *0x1234@6 注意@的用法，其左边必须是你想查看内存处的值，可以直接输出后面的六个变量
类似的 p *argv@argc，也是先取内容转换为变量，再输出

总结一下，用 x 就是直接扫描内存了，简单粗暴；用 p 则是要把你想看的内存区域转化成一个变量，一个 val，不管是 int 还是 int 数组，不管是怎么类型转换，反正基本思想是把内存当成一个变量进行输出。最好还是用 x ，因为效果一样，用 p 你还需要先得到 rsp 里面的值

查看虚表 略

运用 core 文件：gdb debug core进入之后，disassemble，可以看到 => 指向的就是运行出错的地方

性能分析工具

Valgrind：查看内存泄漏

grof：

GPROF 是一种性能分析工具，用于测量程序的运行时间和函数调用频率，以帮助开发人员找到程序中的性能瓶颈。它是 GNU 项目的一部分，通常与 GCC（GNU 编译器集合）一起使用。

GPROF 通过插入计时器代码和函数调用计数器代码来收集程序的运行时间和函数调用信息。它使用两个主要组件来生成性能分析报告：

gprof 编译器：这是一个特殊版本的 GCC，用于在编译时在程序中插入性能分析代码。使用 -pg 选项编译程序时，会将性能分析代码插入到生成的可执行文件中。

gprof 分析工具：这是一个独立的命令行工具，用于解析可执行文件中的性能分析代码，并生成详细的性能分析报告。它会记录程序的函数调用关系、每个函数的运行时间以及函数调用次数等信息，并以可读的格式输出。

使用 GPROF 进行性能分析的一般流程如下：

在编译程序时，使用 -pg 选项告诉编译器插入性能分析代码。例如：gcc -pg -o my_program my_source.c

运行程序，生成gmon.out文件。执行一系列典型的操作，以便 GPROF 能够收集足够的性能数据。

程序运行结束后，在终端中运行 gprof 命令来生成性能分析报告。例如：gprof my_program

GPROF 会分析程序执行期间收集到的数据，并生成一个报告，其中包含函数调用关系图、每个函数的运行时间百分比、函数调用次数等信息。

通过分析 GPROF 生成的报告，开发人员可以确定程序中的热点函数（运行时间最长的函数）和瓶颈函数（被频繁调用的函数），以便进行性能优化。

4 Git

配置

git config --global init.defaultBranch main

找机会修改一下 github 用户名

--global: ~/.gitconfig
--system:/etc/gitconfig

基础命令

5 Makefile

教程

REF1：makefile 简明教程, REF2：如何输出到指定文件夹 ，REF3：关于自动生成依赖.d 文件

模式替换

$(patsubst <pattern>,<replacement>,<text> )
查找中的单词（单词以 “空格”、“Tab” 或 “回车”“换行” 分隔）是否符合模式，如果匹配的话，则以替换。

​ 这里，可以包括通配符 “%”，表示任意长度的字串。如果中也包含 “%”，那么，中的这个 “%” 将是中的那个 “%” 所代表的字串。（可以用 “\” 来转义，以 “%” 来表示真实含义的 “%” 字符）

Copy
$(patsubst %.c,%.o, a.c b.c)
# 把字串 “a.c b.c” 符合模式[%.c]的单词替换成[%.o]，返回结果是 “a.o b.o”

变量替换引用

​ 对于一个已经定义的变量，可以使用 “替换引用” 将其值中的后缀字符（串）使用指定的字符（字符串）替换。格式为$(VAR:A=B)或者${VAR:A=B}

​ 意思是，替换变量 “VAR” 中所有 “A” 字符结尾的字为 “B” 结尾的字。“结尾” 的含义是空格之前（变量值多个字之间使用空格分开）。而对于变量其它部分的 “A” 字符不进行替换。

Copy
foo := a.o b.o c.o
bar := $(foo:.o=.c)
# 注意变量不要带 $
SRCS_NODIR := $(notdir $(wildcard $(SRC_DIR)/*$(SRC_SUFFIX)))
OBJS_NODIR := $(SRCS_NODIR:$(SRC_SUFFIX)=$(OBJ_SUFFIX))

模板 1

Copy
# 一个适合中小规模的makefile模版，基本上自己按照实际情况指定一下 源文件，目标文件，头文件目录，以及源文件后缀就行了。

# ---------------------------------------------------------------------------
# commands
# ---------------------------------------------------------------------------
CC := gcc
LINK := gcc
RM := rm -rf
MV := mv
TAR := tar
MKDIR := mkdir

# ---------------------------------------------------------------------------
# settings
# ---------------------------------------------------------------------------
SRC_SUFFIX := .c
OBJ_SUFFIX := .o
LIB_SUFFIX := .a
BIN_SUFFIX := .exe
DLL_SUFFIX := .so

INC_PREFIX := -I
LIB_PREFIX := -L

OPT_C := -c
OPT_OUT := -o
OPT_LINKOUT := -o

CFLAGS := $(OPT_C)
LIBFLAGS := -Debug

# ---------------------------------------------------------------------------
# directories
# ---------------------------------------------------------------------------
SRC_DIR := ./src
OBJ_DIR := ./obj
INC_DIR := ./inc
LIB_DIR := ./lib /usr/local/lib /lib /usr/lib

# ---------------------------------------------------------------------------
# common settings
# ---------------------------------------------------------------------------
SRCS := $(wildcard $(SRC_DIR)/*$(SRC_SUFFIX))
OBJS := $(patsubst $(SRC_DIR)/%$(SRC_SUFFIX),$(OBJ_DIR)/%$(OBJ_SUFFIX),$(SRCS))
INCS := $(addprefix $(INC_PREFIX), $(INC_DIR))
LIBS := $(addprefix $(LIB_PREFIX), $(LIB_DIR)) $(LIBFLAGS)
TEMPFILES := core core.* *$(OBJ_SUFFIX) temp.* *.out typescript*

# ---------------------------------------------------------------------------
# make rule
# ---------------------------------------------------------------------------
TARGET := loader

.PHONY: all clean

all: $(TARGET)

clean:
$(RM) $(TARGET)$(BIN_SUFFIX) $(OBJS)

$(TARGET):$(OBJS)
$(LINK) $(OPT_LINKOUT)$(TARGET)$(BIN_SUFFIX) $(LIBS) $(OBJS)

$(OBJS):$(OBJ_DIR)/%$(OBJ_SUFFIX):$(SRC_DIR)/%$(SRC_SUFFIX)
$(CC) $(CFLAGS) $(INCS) $(OPT_OUT)$@ $<

模板 2

Copy
CXX := g++

SRC_DIR := ./src
OBJ_DIR := ./build
BIN_DIR := ./bin
INC_DIR := ./include

VPATH = $(INC_DIR) $(OBJ_DIR) $(SRC_DIR)
vpath %.h $(INC_DIR)

# 一种搜索源文件的方式
# SRC_DIRS = $(shell find $(SRC_DIR) -maxdepth 3 -type d)
# SRCS = $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.cpp))
# TODO: 这样子出来的目标文件，在jing'tai时就找不到依赖了
# OBJS := $(OBJ_DIR)/$(notdir $(patsubst %.cpp, %.o, $(SRCS)))

SRCS := $(wildcard $(SRC_DIR)/*.cpp)
OBJS := $(patsubst $(SRC_DIR)/%.cpp, $(OBJ_DIR)/%.o, $(SRCS))
INCS := $(addprefix -I, $(INC_DIR))
BUILDING_DIRS := $(OBJ_DIR) $(BIN_DIR)

TARGET := adb_lab2.exe
RUN := run.sh

$(TARGET) : $(BUILDING_DIRS) $(OBJS)
$(CXX) -o $(BIN_DIR)/$(TARGET) $(OBJS)
@touch $(RUN)
@echo "$(BIN_DIR)/$(TARGET)" > $(RUN)

# 这里的前缀不能少。makefile不会自动去VPATH里面找这几个目标，而是直接当成新的目标来对待
$(OBJ_DIR)/BufferPoolManager.o : BufferPoolManager.h LRUReplacer.h
$(OBJ_DIR)/DataStorageManager.o : DataStorageManager.h
$(OBJ_DIR)/LRUReplacer.o : LRUReplacer.h
$(OBJ_DIR)/main.o : BufferPoolManager.h

# 一个创建运行时依赖文件夹的方法
$(BUILDING_DIRS) :
@mkdir $@

# 这叫 静态模式
$(OBJS) : $(OBJ_DIR)/%.o : $(SRC_DIR)/%.cpp
$(CXX) -o $@ -c $< $(INCS)

.PHONY: all clean output
all : $(TARGET)
clean:
-rm -rf $(BUILDING_DIRS) test.dbf $(RUN)
output:
@echo $(SRCS)
@echo --------------
@echo $(OBJS)

模板 3

🔗自动处理头文件的依赖

Copy
CC := gcc
CC_INCLUDE_FLAGS := -I ./include/
CC_FLAGS := $(CC_INCLUDE_FLAGS) -g

# 程序执行的参数
ARGS := ~/codes

DIR_SRC := ./src
DIR_OBJ := ./build
DIR_EXE := ./bin

SRCS := $(shell find $(DIR_SRC) -name "*.c")
OBJS := $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS))
DPTS := $(patsubst %.c, %.d, $(SRCS))
DIRS := $(DIR_OBJ) $(DIR_EXE)

target := $(DIR_EXE)/my_ls_pro

$(target): $(DIRS) $(OBJS)
$(CC) $(OBJS) -o $@

$(DIRS):
@mkdir $@

$(DIR_OBJ)/%.o: $(DIR_SRC)/%.c
$(CC) $(CC_FLAGS) -c $< -o $@

# set -e : 让终端处于执行命令返回结果不为 0 就终止执行的状态
# gcc -M : 输出所有的依赖关系，-MM 不输出系统的依赖
%.d: %.c
@set -e; \
rm -f $@; \
$(CC) -MM $(CC_FLAGS) $< $(CC_INCLUDE_FLAGS) > $@.$$$$.dtmp; \
sed 's,\(.*\)\.o\:,$*\.o $*\.d\:,g' < $@.$$$$.dtmp > $@;\
rm -f $@.$$$$.dtmp

-include $(DPTS)

clean:
rm -f $(OBJS)
rm -f $(DPTS)

run:
make
$(target) $(ARGS)

6 vim

基本操作

定义宏：q + [a-zA-Z] + your_operation + q，使用时@ + [a-zA-Z]

Ctrl + a光标第一个数字加一，Ctrl + x光标第一个数字减一

行内移动：f w b e

自动补全：Ctrl + p

查询 man 手册：K

:digraphs 列出所有特殊字符

vim 中有很多寄存器，可以用 :reg [xxx] 来查看

a-zA-Z 是用户寄存器，用来存放录制的按键，vim 不会去更改它

0-9 是系统寄存器，里面存放了一些系统定义的东西，比如 0 移动到行首

+ 是系统共享剪切板，"是 vim 临时剪切板，yy dd p 等命令都是用的这个。可以设置二者互通

按住 shift 和鼠标左键，即可在 vim 中选中，并复制粘贴

#：自动查找井号后面的单词

ctrl w ←↑↓→切换窗口，ctrl w HJKL移动窗口

:vertical resize +-n：调整当前窗口宽度，去掉vertical调整高度

默认的map是递归的，比如 a 映射 b，b 映射 c，那么就等于是 a 映射了 c。可以根据使用模式，做非递归的映射，即nnoremap/inoremap/vnoremap/cnoremap(normal/insert/visual/comandline)

doc/help.md・chenxuan/vim-fast - 码云 - 开源中国 (gitee.com)

myvimrc

快速配置：vimfast || 基于vimplus || vim 快捷键help.md || 内置快捷键key.md

Copy
# 我自己的快速配置 √
wget -O ~/.vimrc https://shuaikai-bucket0001.oss-cn-shanghai.aliyuncs.com/config/vim/.vimrc.mine
wget https://shuaikai-bucket0001.oss-cn-shanghai.aliyuncs.com/config/vim/vim-win.tar.gz && cd ~ && tar -xvf vim-win.tar.gz

# 无插件快速配置
wget https://gitee.com/mirrorvim/vim-fast/raw/master/vimrc-no-plug -O ~/.vimrc

通用设置

Copy
let mapleader = "," " 定义<leader>键为逗号[，]
set (no)wrap " 长行（不）换行

打开窗口

Copy
"分屏与竖直分屏
// :split [file]
// :vsplit [file]
"vim中调试
// Termdebug [bug_file] " 打开源代码、gdb、IO三个窗口
nnoremap <leader><leader>d Termdebug<space> " 用[，，d]直接打开此模式
"vim中打开新的终端
// :vert term " vert，即打开竖直方向终端，去掉即水平方向分窗口
nnoremap <leader><leader>t :vert term " 打开竖直终端
nnoremap <leader><leader>t :bo term ++rows=6 "六行水平终端

mybash_aliases

Copy
wget -O ~/.bash_aliases https://shuaikai-bucket0001.oss-cn-shanghai.aliyuncs.com/config/bash/.bash_aliases

7 VScode

C/C++ 环境

插件

inline bookmark

可以对行进行标记，并在左侧列出

Copy
"inline-bookmarks.expert.custom.words.mapping": {"blue": [">mark[\\s]","@mark[\\s]"],"purple": [">panic[\\s]","@panic[\\s]"],"green":[">note[\\s]","@note[\\s]"],"red":[">warn[\\s]",">why[\\s]","@warn[\\s]","@why[\\s]"],"warn": [">todo[\\s]",">TODO[\\s]","@todo[\\s]","@TODO[\\s]"]},

8 编码风格

命名

普通变量

推荐使用下划线隔开单词 (Google 开源风格指南)，也可以使用驼峰命名法，但是不要使用无意义的字母！

tDataNode：t 开头表示这是一个类型，type

kPI：k 开头表示常量，在程序运行中不会被修改

成员变量

以下内容准确性待考究。但首尾下划线一般都表示 “私有” 之意

__foo__: 定义的是特殊方法，一般是系统定义名字，类似__init__() 之类

_foo: 以单划线开头的表示的是 protected 类型的变量或函数，即保护类型，只允许本身和子类访问。也有在后面加下划线的，同理。都是表达 "私有" 之意。

__foo: 以双下划线开头的表示的是 private 类型的变量或函数，即私有类型，只允许本身访问。

C 语言中，单下划线开头表示是标准库的变量，双下划线表示是编译器的变量

注释

参考

文件注释

Copy
/**
* @file 文件名
* @brief 简介
* @details 细节
* @author 作者
* @version 版本号
* @date 年-月-日
* @copyright 版权
* @todo 待办
* @throw 异常描述
* @bugs 漏洞
* @pre 前提条件
* @see [参考]
*/

函数注释

Copy
/**
* @brief 函数描述
* @param 参数描述
* @return 返回描述
* @retval 返回值描述
*/

结构体注释

Copy
/**
* @brief 类的详细描述
*/

常变量注释

Copy
//定义一个整型变量a
int a

int a; /*!< 定义一个整型变量a */
int a; /**< 定义一个整型变量a */
int a; //!< 定义一个整型变量a
int a; ///< 定义一个整型变量a