我们编写C/C++程序使用vs,编译,运行,调试都是一体的,而在Liunx都分开的。
vi/vim 是 Linux 系统内置的不可或缺的文本编辑命令,vi/vim的区别简单点来说,它们都是多模式编辑器,不同的是vim是vi的升级版本,它不仅兼容vi的所有指令,而且还有一些新的特性在里面。例如语法加亮,可视化操作不仅可以在终端运行,也可以运行于x window、 mac os、windows。我们主要学vim。
这里主要讲解vim的三种模式(其实有好多模式,目前掌握这3种即可),分别是命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode),各模式的功能区分如下:
正常/普通/命令模式(Normal mode)
控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入Insert mode下,或者到 last line mode
插入模式(Insert mode)
只有在Insert mode下,才可以做文字输入,按「ESC」键可回到命令行模式。该模式是我们后面用的最频繁的编辑模式。
末行模式(last line mode)
文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作。 在命令模式下,shift+; 即可进入该模式。要查看你的所有模式:打开vim,底行模式直接输入:
help vim-modes
进入vim,在系统提示符号输入vim及文件名称后,就进入vim全屏幕编辑画面:
不过有一点要特别注意,就是你进入vim之后,是处于[正常模式],你要切换到[插入模式]才能够输入文字
[正常模式]切换至[插入模式]
输入a
输入i
输入o
[插入模式]切换至[正常模式]
目前处于[插入模式],就只能一直输入文字,如果发现输错了字,想用光标键往回移动,将该字删除,可以先按一下「ESC」键转到[正常模式]再删除文字。当然,也可以直接删除。
[正常模式]切换至[末行模式]
「shift + ;」, 其实就是输入「:」
退出vim及保存文件,在[正常模式]下,按一下「:」冒号键进入「Last line mode」,例如:
: w (保存当前文件)
: wq (输入「wq」,存盘并退出vim)
: q! (输入q!,不存盘强制退出vim)
光标移到改行最右边
shift + 4 -----> $
光标移到改行最左边
shift + 6 -----> ^
光标到结尾
shift + g -----> G
光标到开头
gg
跳转光标到指定行,n代表的是行号
n+shift+g
左
h
下
j
上
k
右
l
向后按照单词移动
w
支持 nw
向前按照单词移动
b
支持 nb
执行的是光标所在行位置
复制
yy
默认复制一行
nyy
支持光标所在行,进行多行复制 n是行数
粘贴
p
光标在哪里,就向哪里粘贴。默认一次
np
支持对内容,进行多行粘贴
撤销
u
删除
dd
删除光标所在行
ndd
支持光标所在行,进行多行删除
剪切
dd+p
在光标所在行进行剪切
ndd+p
支持多行剪切
取消u操作
ctrl+r
文本行大小写转换
shift+~
文本行批量化替换(当前行文本写错,不想删除,直接shift+r,换一行内容)
shift+r
shift+r其实由命令模式切换到替换模式
替换光标所在行的一个字符
r
替换光标所在行n个字符,只能换成一样的
nr
替换光标所在行的字符,随意替换
R
行内删除,向后删除一个字符
x
向后删除n个字符,包括光标所在位这个位置
nx
向前删除一个字符
shift+x ------>X
向前删除n个字符,不包括光标所在位这个位置
n+shift+x
剪切操作
nx+p
删除光标所在行的单词,并进入插入模式
cw
删除光标所在行n个单词,并进入插入模式
cnw
命令模式切换到插入模式
i/a/o
调出/取消行号
set nu/nonu
强制退出
q!
强制写入
w!
强制写入并退出
wq!
分屏
vs 文件名
无论分多少屏幕,光标只有一个!!光标的意义:选中当前行(编辑的位置)或者屏幕。
光标跨屏幕
ctrl+ww
有了这个指令,就可以尝试在不同文件里进行其他操作了
不退出vim,执行Liunx命令
!+指令
替换
%s/前/后/g
把文件里属于前的内容全部用后的内容替换
1.vim配置是一人一份的,一个用户配置的是自己的,不影响别人。
2.每个人虽然用的都是同一个vim程序,但是大家用的是不同的vim配置,这是因为每个用户,在自己家目录下配置,这样就是独属于自己的配置了。
vim的基本配置
在自己家目录下创建一个.vimrc文件,在里面配置
打开文件,会自动显示行号
感兴趣可以到网上搜索一下vim配置,配置属于你自己的那一份。
这里有一份别人配置好的,分享给大家。
vim配置
往下翻,找到这个,复制这条命令,在自己家目录下执行这条命令
输入root密码,然后等待安装
这样就配置就完成了。自己上手看一下效果,
这里就是我们配置好的文件,不要删除,保留即可
这里配置Tab有一点点问题,打开.vimrc文件
找到这里把2,都修改成4,保存退出,这样完整的一份vim就好了。
1.先把自己切换成root
2.编辑sudoers文件
找到这里,复制粘贴一下,然后强制保存退出,
在sudo提权的时候,输入一下自己的密码就可以正常使用了。
我们知道程序编辑完,ctrl+F5就会把编译和链接都完成了。但是编译到链接又分了几个步骤:
1.预处理(头文件展开,去注释,宏的替换,条件编译)
2.编译(把c语言变成汇编语言)
3.汇编(把汇编语言生成二进制指令)
4.链接(将目标文件和链接库进行链接生成可执行文件)
格式 gcc [选项] 要编译的文件 [选项] [目标文件]
以下面这段代码为例
1.直接完成编译和链接过程生成可执行程序
gcc test.c
./a.out
2.依次处理编译和链接过程
预处理
预处理功能主要包括头文件展开,去注释,宏的替换,条件编译等。
预处理指令是以#号开头的代码行。
实例:
gcc –E test.c –o test.i
选项“-E”,该选项的作用是从现在开始,进行程序的翻译,当预处理完成之后,就停下来
选项“-o”是指形成的临时文件,“.i”文件为已经过预处理的C原始程序
编译
在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。
实例:
gcc -S test.i -o test.s
选项“-S”,该选项的作用是从现在开始,进行程序的翻译,做完编译工作,变成汇编语言后就停下来。
汇编
汇编阶段是把编译阶段生成的“.s”文件转成目标文件(该目标文件不是可执行文件,只是二进制目标文件)
实例:
gcc -c test.s -o test.o
选项“-c”,该选项的作用是从现在开始,进行程序的翻译,做完汇编工作,编程二进制目标文件就停下来
下面指令,可以查看二进制指令
od test.o
做完上面的工作,一定不能忘记链接的过程,因为上面的只是在编译你的代码,就比如说printf是一个库函数,我们直接就使用了,头文件展开只是告诉这个函数怎么用,有这个函数。并没有定义它,必须要去库里面找。
链接
把自己写的代码与C标准库的代码合起来形成可执行程序
实例:
gcc test.o -o mytest
指定可执行程序名称
gcc test.o
形成可执行程序默认名称为a.out
如果想执行C++代码,把gcc换成g++
就如上面所说,printf我们并没有去定义实现它,头文件包含了对该函数的声明,而没有定义函数的实现,那么是在哪里实现printf函数的呢?
答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用
链接的本质:就是我们调用库函数的时候,和标准库如何关联的问题。
函数库分为动态库和静态库。
静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”
动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。
动态库和静态库优缺点:
优点:
动态库:形成的可执行程序小,节省资源(内存,磁盘,网络)。
静态库:不受库升级或者被删除等影响。
缺点:
动态库:受到库升级或被删除等影响
静态库:形成可执行程序太大
gcc默认生成的二进制程序,是动态链接的,这点可以通过 file 命令验证
file mytest
查看可执行程序依赖的动态库列表
ldd mytest
动态库
libxxx.so
lib前缀
.so后缀
去掉前缀和后缀,剩下的就是库名称
静态库
libxxx.a
lib前缀
.a后缀
Liunx下默认形成可执行程序使用“动态库”
动态
gcc test.c -o mytest
静态(需要指定)
gcc test.c -o mytest -static
注意
如果系统中只提供.so文件,只能用动态链接,或者只提供.a文件,即使不指定static也是静态链接。如果动静态库都有,默认使用动态库。
一般而言,系统会自动携带动态库的,这是因为系统的运行就需要动态库。静态库如果不存在需要自己手动安装。
安装C静态库
sudo yun install -y glibc-static
安装C++静态库
sudo yum install -y libstdc++-static
关于Liunx的动静态库的问题,在windows下原理是一样的。
默认形成可执行程序:动态链接
windows下动态库后缀.dll,静态库后缀.lib
注意:系统本身为了支持我们编程,除了提供标准库.h,还提供了标准库的实现.so/.a
Liunx和windows调试方式不一样,但调试思路是一样的。
Liunx是使用gdb命令行调试
1.程序的发布方式有两种,debug模式和release模式。
2.Linux gcc/g++出来的二进制程序,默认是release模式。gdb不能直接对release模式下发行的程序进行调试,需要改成debug模式下发行的程序。
3.生成debug模式下的程序,必须在源代码生成二进制程序的时候, 加上 -g 选项
总结:
gcc默认行为
1.默认动态链接
2.默认release模式
vim默认行为
1.默认打开就是命令模式
开始调试
gcc test.c -g -o mytest
gcc mytest
退出调试
q
下面命令都是简写,也可以使用完整的命令
显示代码
list
l
从0行开始显示代码
l 0
这里显示代码并不会完全显示出来,再按回车键继续显示
在n行设置断点
break
b n
查看断点
info b
删除断点
delete
d 编号
调试运行,跑到断点处
run
r
逐过程
next
n
逐语句
step
s
跳转到下一个断点处
contiue
c
查看函数调用堆栈
bt
执行当前函数返回,然后停下来等待命令
finish
查看变量/地址
p,只显示一次
p 变量/地址
常显示
display 变量/地址
取消常显示
undisplay 编号
跳转到指定行
until n
修改变量的值
i是变量
set var i=100
显示当前栈帧局部变量的值
info locals
禁用断点
disable breakpoint 编号
启用断点
enable 编号
1.会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
2.一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
3.makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
4.make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
5.make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
makefile存在的意义:是为了构建项目(做一件事情)。
构建项目需要:1.依赖关系 2.依赖方法
比如,要做一件事情,找你爸要钱。
a.表明依赖关系(我是你的儿子/女儿)
b.表面依赖方法(你得给我转钱)
第一行依赖关系,:左边是目标文件/可执行程序,:右边是依赖文件列表
第二行依赖方法,必须以Tab键开头
依赖关系:目标文件/可执行程序与源文件互相依赖关系
依赖方法:根据依赖关系,从依赖文件列表生成目标文件/可执行程序
有了可执行程序,还需要一个删除可执行程序指令。
.PHONY:被该关键字修饰的对象是一个伪目标,该目标总是可以被执行
发现只能make一次,make clean可以执行多次,gcc是如何得知,我不需要编译了呢?
stat 文件名(查看文件属性)
Access:文件被访问的时间
Modify:文件内容被修改的时间
Change:文件属性被修改的时间
修改文件内容的时候,发现文件属性也变了,这是为什么?
因为文件大小变量,属性也就变了。文件属性包括:文件名,类型,大小。。。
至于大家看到Access也变了,下面就解释。
当我们读取内容的时候,发现有的时候Access时间不变,这是为什么呢?
首先回答,文件操作时,改文件内容多,还是访问多?
肯定时访问多。如果一访问就修改Access的时间,需要进行多次IO操作,其次没人会关心访问文件多少次。
因此,一段时间访问次数够了,Access才会变。
gcc是根据对比源文件和可执行程序的Modify时间的新旧来判断,来判断可执行程序是否重新编译。
源文件比可执行程序时间旧,就不用重新编译,如果新就重新编译。
因此凡是被.PHONY修饰的,不再根据对比modify时间新旧的策略,而是总是执行一次。
问:
为什么make,就可以执行makefile第一条规则,执行第二条规则必须make clean?
答:
make默认从上到下扫描文本,默认第一个被扫描的目标文件,可以省略名称。
问:
make为什么走完第一条规则就不往下走了?
答:
默认情况下makefile只形成一个目标文件,后续的依赖关系和依赖方法不再执行,默认从上到下扫描只执行第一个。默认不指定就执行第一个。
mytest:test.c
其实mytest并不直接依赖test.c
真实情况是这样
mytest:test.o
gcc test.o -o mytest
test.o:test.s
gcc -c test.s -o test.o
test.s:test.i
gcc -S test.i -o test.s
test.i:test.c
gcc -E test.c -o test.i
mytest依赖test.o,test.o不存在因此不执行依赖方法,然后去找test.o。。。。最后test.i依赖test.c,test.c存在执行依赖方法,然后层层返依次执行。
但是不推荐这样写,直接mytest:test.c,下面跟着依赖方法就行了。
自此关于Liunx编辑器vim,编译器gcc/g++,调试器gdb,vim配置,sudo配置,以及简单了解Liunx项目自动化构建工具make/makefile到这里暂时告一段落。
觉得有帮助的,点赞,评论,收藏,谢谢!!!