vim
1、三种模式:
- 命令模式(默认)—> (aios或AIOS)—> 编辑模式 —> (esc)—> 命令模式
- 命令模式(默认)—> (:)—> 末行模式 —> (esc×2)—> 命令模式
2、命令模式下:
- h(前),j(下),k(上),l(后) 负责光标的移动
- 光标移到头部(0),尾部($),文件头部(gg),文件尾部(G),5行(5G)
- 删除光标所在的1个字符(x,删错了想撤销就u),删除光标前的1个字符(X)
- 删除光标前面的所有字符(d0),删除光标后面的所有字符(d$或D)
- 删除光标所在的行(dd),删除4行(4dd)
- 以上删除的东西都在后台的一个剪切板里面
- 粘贴(p或P),复制(yy),复制4行(4yy),也可以进可视模式(v)来选中部分内容
- 查找(/或?关键词,然后用n或N来切换),亦或者移动到单词身上按 #
- 单个字符替换(移到要替换的词身上,r+替换的字符)
- 改缩进(>>向右或<<向左)
3、末行模式下:
- 跳转到相应行(:行号)
- 替换所有字符串(:%s/原串/新串/g)
- 分屏(水平:sp ,垂直分屏:vsp,可接文件名),切换就Ctrl+w,关就q
4、配置文件
- 系统级配置文件目录:
/etc/vim/vimrc
- 用户级配置文件目录:
~/.vim/vimrc
gcc
1、gcc编译的4个阶段:
2、gcc的一些其他参数
- 指定头文件路径(
$ gcc test.c -I ./include -o app
) - 编译时指定宏(
$ gcc test.c -o app -D DEBUG
) - 优化程序(-O0不优化,-O1,-O2,-O3最高优化)
- 编译时输出警告信息(-Wall)
- 添加调试信息(-g),可执行程序会变得稍大一些,便于gdb调试
动态库和静态库
1、静态库
命名规则:
lib + 库的名字 + .a
制作静态库:
- 生成
.o文件
并打包(ar rcs + 静态库的名字 + 所有生成的.o文件)
发布静态库:
- 需要
静态库和头文件
特点:
- 优点:把库都打包到了可执行程序中,于是发布程序时不需要再提供对应的库,所以库的加载速度会非常快
- 缺点:相应的应用程序会比较大。如果库发生改变,那么应用程序需要重新编译
静态库制作实例:
1、目录结构
2、在src目录下制作静态库
$ gcc *.c -c -I../include
,生成相应的与位置有关
的.o文件
$ ar rcs libCal.a *.o
并移动到上级的lib目录
下3、把 lib 和 include 发布给用户,用户根据.h文件中的内容编写程序即可
- 方法1:
$ gcc main.c lib/libCal.a -o app -I./include
- 方法2:
$ gcc main.c -I./include -L lib -l Cal -o app
2、动态库
命名规则:
lib + 库的名字 + .so
发布动态库:
- 需要
动态库和头文件
特点:
- 动态库不会被打包到可执行程序中,只是做了一个符号的记录(调用哪一个动态库中的哪一个函数)。
- 在
程序运行起来之后
才去加载动态库到虚拟地址空间堆和栈之间的区域,所以每次动态加载的位置都不一定,这称为与位置无关- 所以,可执行程序小,更新动态库以后在接口不变的情况下一般不需要重新编译程序。
- 但加载速度相对较慢,而且需要把动态库提供给用户。
动态库制作实例:
1、目录结构
2、在src目录下制作动态库
$ gcc -fPIC -c *.c -I../include
,生成相应的与位置无关
的.o文件
$ gcc -shared -o libCal.so *.o -I../include
生成动态库并移动到上级的lib目录
下3、把 lib 和 include 发布给用户,用户根据.h文件中的内容编写程序即可
- 方法1:
$ gcc main.c lib/libCal.so -o app -I./include
- 方法2:
$ gcc main.c -I./include -L lib -l Cal -o app
值得注意的是,在执行方法2生成的可执行程序时会出现下面的错误
这是因为链接不到动态库的原因。此时通过$ ldd [可执行程序名]
来查看可执行程序在执行时所依赖的所有动态库
此时可以看到,c标准库和其他依赖的库都被找到了,只有我们的cal库没有找到。其中,最后一行是动态链接器,上面的几个动态库都是通过它来加载到应用程序中的,那么为什么其他库都找到了而我们的库却没有找到呢?——环境变量
。所以,这个动态链接器会根据环境变量里的value值依次去查找。- 解决方法1:
回想起linux目录结构中,根目录下的lib文件夹就是存放基本的动态链接库的,于是可以将我们的动态链接库拷贝到根目录下的lib目录中,这就找到了。但这是系统目录,为防止同名把系统原来的库给覆盖,这种方法一般不使用
- 解决方法2:
使用环境变量LD_LIBRARY_PATH
,把你的库所在的路径指定给这个环境变量,这样,它会先搜索这个地方,然后再去搜索默认的环境变量中的路径。
但这种方法只是临时的。那么如何做到永久呢?——设置到当前用户的bashrc文件中($ vim ~/.bashrc
)。
在最后一行,加上绝对路径的导入export LD_LIBRARY_PATH=/home/..../lib
,关掉当前终端再打开即可。- 解决方法3(最常用):
首先找根目录下的etc文件夹内的动态库的配置文件($ sudo vim /etc/ld.so.conf
),在最后一行直接添加动态库的目录,保存并更新($ sudo ldconfig -v
)。
gdb调试
gcc参数加-g
生成带调试信息的可执行程序
$ gdb 可执行程序
,启动gdblist fileName:行号或者函数名
,查看对应文件的代码,默认看mainbreak 行号
,在相应的行打断点break 行号 if i==5
,在相应的行打条件断点info break
,查看断点信息start
,执行程序(只执行一步),run
则是执行程序直到跑到断点位置next
,单步调试continue
,一直跑直到断点处step
,进入函数体,此时会显示函数的形参具体的值print 变量
,打印变量的值ptype 变量
,打印变量的类型display 变量
,追踪变量的值,一般用在调试循环中。去掉就用info display
来获取变量对应的编号,然后undisplay 编号
即可u
,跳过这一次循环finish
,跳出当前函数,前提是要删掉里面的断点(delete 断点编号
)set var 变量=值
,设置变量的值quit
,退出gdb
此外,当出现断错误时,进入gdb直接run,停下的地方就是段错误的地方。
Makefile
1、三要素
- 目标、依赖、命令
目标:依赖
(Tab)命令
意味着执行这个命令,需要上面的依赖(如果不在同一级目录,要显式指定),最终生成目标
make即可,上面的依赖文件都会被编译。所以当文件比较多的时候,效率较低。
为此
改哪个编哪个,分开编译
。app为终极目标,其他.o都是子目标。这是一个关系依赖树。
向下找依赖,向上执行命令
当要生成终极目标app时会查找依赖,发现没有main.o这个依赖,于是向下查找看有没有一条规则是生成这个依赖的。最后才执行第一条规则来生成终极目标。这样,在只修改其中一个文件后再去编译时,将只会编译修改的那个文件(通过目标
和依赖
的时间关系来判断)。优化: