vim
vim简绍
在window中写代码一般会使用像vs这样的集成开发环境软件,vs里写完代码就会自动编译链接然后执行。linux中一般是将这几个步骤分开的,vim就是用来编辑写代码的。
vim是一款多模式的编辑器,常用的模式有三种:命令模式、插入模式、底行模式。
插入模式:用来在输入信息
命令模式:对文本内容进行编辑,就像我们在用window写笔记,会使用鼠标对文本内容进行复制、删除、选中等操作一样。
底行模式:用来进行但不限与vim和shell的交互
三种模式的切换:
命令模式直接输入a/i/o进入插入模式,插入模式按Esc切入命令模式;命令模式输入:进入底行模式,底行模式按Esc切入命令模式;底行和命令模式不能进行切换。
模式下的指令:
vim下的指令都很简单,只有去vim下使用才会更好的看到效果并理解,所以下面只会说明指令的作用,不会配图看效果。
命令模式:
vim一进来就是在命令模式下。
i:光标位置不变进入插入模式
a:光标向后移动一个位置进入插入模式
o:光标在当位置下一行另起一行进去插入模式
n+yy:复制当前行 n:表示连续复制n行,输入的是数字,下面的也一样
n+p:粘贴到当前光标的下一行
n+dd:剪切/删除
u:撤销
ctrl+r:对历史撤销,进行撤销
$(shift+4):将光标定位到当前行的结尾
^(shift+6):将光标定位到当前行的开始
gg:将光标定位到整个文件的开头
G:将光标定位到整个文件的最后一行
n+G:将光标定位到文件的第n行
h,j,k,l:左,右,上,下,也可以带n。和上下左右键一样
w:按照单词为单位进行光标后移
b:按照单词为单位进行光标前移
~:大小写切换
n+x:删除光标后续的一个字符,带n也只能删除一行内的
n+X:删除光标前面的一个字符
n+r:对光标指定的位置,进行一个字符的替换
R:进入替换模式,直接进行文本替换,Esc退出
ctrl+v:区域选择后,输入shift+i可以在选择区域每行的光标位置进行插入,Esc*2退出;输入d将选择的区域删除
ZZ:保存并退出
底行模式:
w:保存
q:退出
wq:保存退出
Ctrl+z:将vim更改为后台进程。
vim在没有保存的情况下被强制退出(不包括!p),会生成文件.[vim打开的文件名].swap,vim打开原文件会进入下面的界面
生成文件的路径在第二行“”括起来的地方,我们可以E/R进去文件保存退出后,重新进入D删除.swap文件,或通过路径去删除。不想恢复保存的文件就直接删除。
[指令]!:强制执行
set nu、nonu:打开行号、去掉行号
/[关键建]:搜索文件中的关键字
![shell命令]:不退出vim就可以进行shell命令
vs [文件名]:分屏多文件操作,ctrl+ww:切换光标所在屏幕位置,光标在哪个屏幕内就编辑哪个文件
如何使用sudo
vim /etc/sudoers,使用vim打开这个文件,在100行的位置,将想让使用sudo的用户以root在里面的形式添加到下面。
这里要使用root完成这个操作,普通用户没有写的权限。
在保存退出时会出现下面的报错,这很正常,使用wq!强制保存退出就可以了。
配置
vim不是直接执行的,它会先读取若干配置文件,.vimrc。没有就直接执行。每个用户的配置都是独立的。
先来测试一下,在家目录创建一个.vimrc,在里面写入set nu。
再使用vim打开文件就会直接带有行号。
可以直接去搜索vim的基本配置拷贝自己想要的功能到.vimrc。
gcc,g++
gcc是用来编译c语言文件的,g++是用来编译c++文件的。
语法:gcc [.c文件] g++ [.cpp,.cc,.cxx文件]
.cpp, .cc, .cxx都表示c++文件。我们知道在c++环境下是兼容c的,这里g++编译器也可以编译.c文件。编译成功后会形成a.out可执行文件,+ -o选项可以修改可执行文件名。
gcc [.c文件] -o [文件名]
g++的选项和gcc的选项是一样的
使用sudo yun install -y gcc-c++, g++ -v查看安装的编译器默认是低版本4.8.5,编译c/c++时可以使用-std=c99/-stdc++11来让编译器可以对新版本的语法进行编译,也可以去更新最新版本,不过底版本更适合来学习。
程序的翻译过程
过程:预处理 -> 编译 -> 汇编 -> 链接
预处理:宏替换,头文件展开,去注释,条件编译
编译:语法检查,将c语言编译为汇编语言
汇编:将汇编编译为二进制目标文件
链接:形成可执行文件
可以通过gcc的指令来观察整个过程
预处理:
gcc -E [.c文件] -o [.i文件]
-E:从现在开始进行文件的翻译,预处理结束后停下
-o:如果不带-o,-E后会将结果打印到显示器,-o将结果写入到后面的文件名中
生成出test.i文件后,可以看出确实完成了宏替换,去注释,头文件展开。
条件编译在这里还可以实现其他功能,先将代码改一下:
这段代码表示M1存在就输出功能1,2;M2存在输出功能1,2,3;M1和M2都为定义输出功能1,2,3,4。上面的代码并没有任何定义,它只能匹配else。而我们可以在gcc编译时加入-D选项,指定创建一个宏。
gcc -D [宏定义] [.c文件]:-D后面只能跟一个宏定义,可以多次使用-D
有了这个功能就可以想象一下,一家公司做了一款软件,这个软件可能有社区版、免费版、专业版等。这些版本是存在功能上的一些区别,如果没有预处理命令,每一个版本都要独立的代码,里面只是功能上有些区别,空间和维护的成本都是很高的。使用预处理命令就只需要在执行时定义一些宏就可以完成功能的转变,这样维护成本就会大大降低。
编译:
gcc -S [.c/.i 文件] -o [.s文件]
-S:从现在开时对文件进行编译,编译完成就停下来。对.c或.i文件使用都可以。
里面是汇编的代码。
汇编:
gcc -c [.c/.i/.s文件] -o [.o文件]
-c:从现在开始对文件进行翻译,汇编完就停下来。
里面存放的是二进制,文本格式打开就是乱码。这虽然是二进制文件,计算机也就是识别二进制的,但依旧不能执行,因为它还没有经过链接库,本身也不是可执行文件。
链接:
gcc [.c/.i/.s/.o文件] -o [文件名]
这里就和直接使用gcc一样,不带-o就会形成a.out文件。
动静态链接:
链接分为两种动态链接和静态链接,Linux对应的是动态库(.so文件)和静态库(.a文件),Window是动态库(.dll文件)和静态库(.lib文件)。c语言默认的链接就是动态链接,可以用ldd查看它的动态链接。
主要查看中间的那条链接,
它指向了一个lib-2.17.so的动态库,这个库就是c语言的标准库,存放我们头文件的函数printf、scanf、strlen等的实现。我们在使用这些函数时就是因为链接了标准库,才能去到里面调用。
c语言也是有自己的静态库,编译时带-static就是链接静态库,不过linux是没有自带c语言的静态库的,yum install -y glibc-static libstdc++-static,需要先安装静态库。
可以看到使用静态链接后的a.out是比动态链接的大很多的。这是因为动态链接是到动态库内调用的,并不用占有多大空间,而静态链接是将静态库的内容拷贝过来,程序的内容链接后也就增大了。
应用场景:
动态链接,首先就是语言上的使用基本都是动态链接的,还有linux的指令也都是有动态链接。
静态链接,例如在一家公司,有一台电脑要将一个可执行文件传给其他电脑,可这个可执行文件需要b库才能正常使用,其他的电脑上只有一部分是安装了b库,那要用动态链接就需要所有电脑安装b库很麻烦,而把程序改成静态的就不需要考虑安装库了。
优缺点:
动态:优点,节省空间,维护性强;缺点,不能丢失
静态:优点,一旦形成与库无关;缺点,占空间大
c编译器的发展过成:
c语言的编译是先到汇编,再到二进制,感觉很繁琐,这跟语言的发展史是有关的。
最开始因为计算机只认识0和1,那时通过打孔纸带来输出指令,
机器使用光扫描上面的孔,有孔能透过光就是1,反之为0,这就是最早期的二进制编程;后来有了汇编语言,使用二进制写了汇编语言的编译器,然后再用二进制写的汇编语言编译器,去使用汇编语言编写一个汇编语言的编译器;c语言也是这样形成的,这种方式被叫做编译器的自举过程。
make,makefile
make是一个命令,makefile是一个文件。make是用来执行makefile内的命令,make只能执行当前目录下的makefile。
makefile内有自己的语法,编写一些代码来看makefile的基本语法规则。
创建makefile,写入一些编译和删除的指令。
test.exe和clean表示目标文件;:后面是依赖列表,test.c是依赖列表中的一个依赖文件;目标文件下面的一行是依赖关系,如果执行目标文件时,没有足够的依赖文件就无法执行依赖关系。
写一个test.c,用make来编译和删除。
make [makefile的目标文件] :执行目标文件的依赖关系,前提是有足够的依赖文件才能执行。
直接使用make,它会执行makefile的第一个目标文件。
当连续执行同一目标文件,make就会检查test.exe是不是最新的可执行文件,不是才会继续执行。
它是通过查看文件的修改时间来确定是不是最新的,stat:查看文件的信息
可以看到test.exe的修改时间明显在test.c后,所以test.exe就是最新的。
使用touch修改一下test.c的时间,来看看能否再使用make。
这时test.c时间在test.exe后面就可以使用后make。如果想要一直执行目标文件,可以在声明目标文件前使用.PHONY修饰目标文件,表示目标文件一直可执行。
$:替换符
$^:依赖列表
$@:目标文件
$(变量) :替换为定义的变量
@[依赖关系]:make时不显示依赖关系
#:注释符
gdb
作用
yum -y install gdb安装,gdb -v查看是否安装完成。
安装完成的界面:
gdb作用调试代码
使用VS编译是有两种环境Debug和Release,Debug下形成的文件会生成调试信息,才可以使用gdb。直接使用gcc对其文件进行编译形成的是Release文件,无法调试,编译时带-g选项就会形成Debug的文件。
可以看到test.exe-Debug的大小是大于test.exe的。
使用
gdb [可执行文件名]:进入调试
quit/q/ctrl+d:退出gdb
list/l [行号]:显示文件源代码行号的上下文,只会显示10行
下面的空行是直接按的回车,gdb会记住上一次使用的指令,直接按回车就会执行。对于list指令gdb会记住前一次最后一行的行数,显示后面的代码。查看全部代码 list 0 一直回车就可以,查看指定区域指定行号就可以,查看函数 list [函数名]。
run/r:运行程序。相当于使用vs的F5
break/b [行号/函数名]:设置断点。vs的F9
b 函数名,是会在进入函数的第一条语句上打断点。r运行到第16行就停下了。
info/i break/b:查看断点信息
Num:断点编号。每个断点都有固定的编号,线性增长不会重复使用(除非重新打开gdb)。
End:使能。这个断点是否被使用 y(使用中) n(没使用)。
What:断点位置
d [编号]:删除编号对应的断点。只能使用编号删除
d:删除所有断点
disable,enable [编号]:打开,关闭断点的使能。
可以看到这回运行没有在16行停止,进入函数后在第4行停下了。
next/n:逐过程:vs的F10
逐过程是不会进入函数的,这里进入是因为在第4行打了断点。
step/s:逐语句。vs的F11
print/p [变量/地址]:查看变量内容或地址。只能一个一个查看
display [变量/地址]:一直显示变量内容或地址
undisplay [编号]:删除变量或地址。
continue/c:运行至下一个断点处
代码从16行直接运行到了15行,后面没有断点直接结束。
finish:运行结束所在函数后停下。
运行代码到第5行进入sum_up函数,使用finish运行所在函数后停下了回到main函数,main内使用finish不会运行,它没有任何意义。
until [代码行号]:运行到指定的代码语句。行号如果是已经运行过的,会根据指定行号的区域来跳转位置。