在之前我们已经学会了如何创建一个文件,那么如何像windows一样进行文件内容编辑呢?先做一个简单的示例:
先创建一个文件
然后使用 vim/vi 来进行编辑
这个时候就可以对文本进行编辑了,这个时候还不能直接写入一些内容,先来,了解一下 vim 编辑器的基本使用方法;
所谓的普通模式也就是下面的模式
在此模式下我们可以进行以下的基本操作:
控制屏幕光标的移动,字符、字或行的删除,移动复制,及进入插入模式下,或者到底行模式。
常用:
1.上下左右移动
当 vi 一个文件时 可以使用 键盘的上下左右箭头进行光标移动 ,也可以使用H J K L 进行 的移动。
2.gg=G全文对齐
3.ESC 模式切换
4.shift + : 进入底行模式
5.i/a/o :进入插入模式
光标移动:
按 [ G ]:移动到文章的最后
按 [ $ ]:移动到光标所在行的行尾
按 [ ^ ]:移动到光标所在行的行首
按 [ w ] :光标跳到下个字的开头
按 [ e ]:光标跳到下个字的字尾
按 [ b ]:光标回到上个字的开头
按 [n | ]:光标移到该行的第n个位置,如:5 | 跳到该行的第五个位置
按 [ gg ]:进入到文本开始
按 [ shift + g ]:进入文本末端
按 [ ctrl +u ]:屏幕往“后”移动半页
按 [ ctrl + d]:屏幕往“前”移动半页
删除:
[ x ]:每按一次,删除光标所在位置的一个字符
[ nx ]:例如,2 x 表示删除光标所在位置的后面(包含自己在内)2个字符
[ X ]:大写的X,每按一次,删除光标所在位置的“前面”一个字符
[ nX ]:例如:20X,表示删除光标所在位置的“前面”20个字符
[ dd ]:删除光标所在行
[ ndd ]:从光标所在行开始删除n行
更改:
[ cw ]:更改光标所在处的字到字尾处
[cnw ]:例如,c4w表示更改4个字
复制粘贴:
[ yw ]:将光标所在之处到字尾的字符复制到缓冲区中。
[ nyw ]:复制n个字到缓冲区
[ yy ]:复制光标所在行到缓冲区。
[ nyy ]:例如,6yy 表示拷贝从光标所在的该行“往下数”6行文字
[ p ]:将缓冲区内的字符贴到光标所在位置。
注意:所有与“y”有关的复制命令都必须与“p”配合才能完 成复制与粘贴功能。
撤销上一步操作:普通模式切换到插入模式:
插入模式:
按 " i " 切换进入插入模式,从光标当前位置开始输入文件
按 " a " 进入插入模式后,是从目前光标所在位置的下一个位置开始输入文字
按 " o " 进入插入模式后,是插入新的一行,从行首开始输入文字
从插入模式切换为命令模式:
按ESC键,切换模式
底行模式多用于保存文件退出,以及一些其他的查询显示等;
2.保存文件,退出编辑器进入末行模式后 :
w : 保存当前文件
wq : 保存并退出
q :直接退出
q! : 不保存强制退出
[ set nu ] 列出文件的每一行的行号
[ /keyword ] 查询关键字 n 可以到下一个关键字的位置
按住 " ? " 输入关键字也可以进行查询 n 查找下一个关键字
不同之处:/ 是向后查找 ?是向前查找
注意 " / " 和 keyword 之间不要有空格
[ n ] : 在 " :" 之后直接输入行数 会直接跳到该行:
写在前面:
我们所写的C语言代码,是不能被机器直接执行的:
因为C语言是一个高级语言 ,所写的代码不是一个机器能够识别的:
早期程序都是汇编写的- -移植性差
汇编语言是贴合电脑底层操作系统指令进行运行的 因此这时候就需要编译器来讲这些高级语言做些的代码翻译成为机器能够识别的指令集
gcc是C语言的编译器 g++ 是 C++的编译器:
编译器将高级语言代码解释为机器指令集所经过的过程
首先我们回顾以下内容:
1.预处理:展开所有代码(宏替换,头文件引入,去掉注释)
2.编译:进行代码语法予以纠错,没错则将C语言程序解释为汇编指令
3.汇编:将汇编指令解释为机器可识别指令(二进制指令)
4.链接:将所有使用到的代码(可以是自己的另一个 .o 文件 也可能是一个库文件)都打包到一起最终生成一个可执行程序,链接所有的文件)
注:链接有两种方式:动态链接,静态链接。
链接实际上就是把其他的代码都拿过来生成可执行程序
1.动态链接:
在生成可执行的程序文件中并不写入具体库函数的实现代码,
而是在可执行程序文件中记录了函数符号信息表
好处就是生成的执行程序文件比较小,但是因为可执行程序中没有这些代码,
因此运行程序的时候不但要加载可执行程序而且还要加载这个库到内存中 ,
但是这种方式也有一个好处:多个程序在内训中可以使用同一个库 代码冗余比较小
2.静态连接:
在生成可执行程序的时候直接将库中的代码写入到了可执行程序文件中
因此运行程序的时候就不需要加载库文件了
但是若干个程序都是用来同一个库 则会造成代码冗余
注意:gcc 默认使用动态链接
那么linux 下的编译器是如何进执行这一系列操作,如何在linux下执行一个写好的程序呢?
假设我们现在有个简单的 打印hello world 的程序,文件是 helloworld.c ,这个程序该如何进行执行呢?
gcc -E helloworld.c -o helloworld.i
-E 只进行预处理 -o 输出文件预处理产生的文件后缀是.i
gcc -S helloworld.i -o helloworld.s
-S 只进行编译 编译产生的文件后缀是.s
gcc -c helloworld.s -o helloworld.o
-c 只进行汇编,生成的文件是.o文件
gcc helloworld.o -o helloworld
打包为 helloworld 可执行程序,可以直接执行
最后执行 helloworld
同时我们也可以查看在预处理编译汇编链接这几个过程中产生的几个文件里的内容:
预处理 .i 文件
可以看到除了我们自己写的代码以外还有很多的其他的代码,也就是在预处理时展开的一些头文件的内容。
编译 .s 文件
汇编 .o 文件
gcc常见选项:
-E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面
-S 编译到汇编语言不进行汇编和链接
-c 编译到目标代码
-o 文件输出到 文件
-static 此选项对生成的文件采用静态链接
-g 生成调试信息。GNU 调试器可利用该信息。
-shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
-O0 -O1 -O2 -O3 编译器的优化选项的4个级别,
-O0表示没有优化,
-O1为缺省值,
-O3优化级别高
-w 不生成任何警告信息
了解了上述的编译过程,这是生成一个可执行文件的过程,假如有很多的文件这时不是无形中增加了很多的步骤,那么这时候引入 make/Makefile的概念
Makefile — 普通的文本文件–这个文件中记录着一个项目的编译流程以及规则
make – Makefile 的解释器 就是一个程序 ,找到Makefile 文件 按照流程逐行解释执行其中记录的项目构建规则
Makefile 的编写规则:
目标对象:依赖对象 (通过依赖对象来生成目标对象)
Tab \ t ,命令(执行这条命令,完成目标对象的生成)
注意这里 gcc之前的必须是Tab键,空格键会发生错误)
预定义变量:使用在命令中的变量
$^ : 所有的依赖对象
$< : 表示历来对象的第一个
$@: 表示目标对象
注意:
依赖对象的作用就是与目标对象进行最后一次修改时间的比较:若依赖对象比目标对象时间更靠近当前,则意味着上一次生成后,源码又发生改变
伪对象:目标对象不管是否存在,每次都需要重新生成。
如何声明伪对象:
.PHONY:对象名称
1.在命令行敲击make 回车 ,则会运行make程序,到当前目录下找到Makefile文件,去解释其中的规则
2.make会在makefile 中找第一个目标对象,然后执行下边的指令
3.但是make会检测这个目标对象的依赖对象是否存在
注意少写一个就会出现错误
调试器 gdb写在前面:
要对程序进行调试就肯定需要用到调试器,linux 中的调试器是 gdb
程序的发布方式有两种,debug模式和release模式
Linux gcc/g++出来的二进制程序,
默认是release模式
要使用gdb调试,必须在源代码生成二进制程序的时候,
加上 -g 选项否则在调试时就会出现以下情况
例如:
示例:
gcc -g helloworld.c -o helloworld
在linux下如何调试一个程序呢?比如打断点,逐步执行,查看变量等等;
1.开始调试命令:run 直接运行程序:
start 开始逐步调试:
两者都是直接重新开始
list 查看调试行附近代码 简写 (i) (上下5行的内容)
next 下一步 简写(n) 遇到函数直接运行完毕
step 下一步 遇到函数会跟踪进入函数
continue 继续运行 不再逐步调试
until file :n 直接运行到文件的n行
例如: until test.c : 20 直接运行到test.c 的第20行
3.断点相关命令:break filename.c : n 在 n行打一个断点 直接运行到 n 行
eg: break test.c : 24
info break 查看断点信息
delete 删除断点
eg: delete break_id
break 函数名:在某个函数开头设置断点
特殊断点:给一个变量加一个断点 如果这个变量发生变化 就会停下来
watch 一个变量
delete breakpoints:删除所有断点
delete breakpoints n:删除序号为n的断点
disable breakpoints:禁用断点
enable breakpoints:启用断点
info(或i) breakpoints:参看当前设置了哪些断点
backtrace 查看函数调用栈-快速定位程序崩溃退出位置
print 查看变量内容 简写 p
set var:修改变量的值
display 变量名:跟踪查看一个变量,每次停下来都显示它的值
undisplay:取消对先前设置的那些变量的跟踪
until n行号:跳至n行
info(i) locals:查看当前栈帧局部变量的值
quit(q):退出gdb