Linux基本工具:vim编辑器,gdb调试器,makefile项目自动化构建工具,git

vim编辑器的三种模式

用vim编辑器打开一个文本,默认是命令模式,想对文本输入内容

1.敲一个i进入插入模式
2.想回到命令模式,Esc返回
3.从命令模式进入底行模式,输入一个冒号,回到命令模式同理
底行模式和插入模式不能直接转换
在这里插入图片描述

vim命令模式的一些常用操作

yy,复制当前文本行,nyy从光标处开始向下复制n行文本
p,粘贴到光标的下一行,np重复粘贴n次
dd:剪切,ndd从光标处开始向下剪切n行文本
shift + 4,将光标移动到当前文本行的末尾
shift + 6,将光标移动到当前文本行的开始
shift + g,移动到文本的末尾
gg,移动到文本的开头
u,撤销操作
ctrl+ r,撤销上一次u的操作
n + shift + g移动到文本的第n行
r,替换当前字符
shift + r,类似insert,批量化替换
shift + ~,大小写转换
w,b,当前行的后移,前移,以单词为单位的移动
h,j,k,l,左下上右

编译过程的感性认知

一段文本要转换成机器能看懂的语言要经过翻译和链接两步,其中翻译又细分为三个部分:预处理,编译,汇编,这些过程都做了什么?

1.预处理:宏替换,头文件展开,去注释,条件编译(将代码变得干净)
2.编译:将干净的代码转换成汇编代码
3.汇编:将汇编代码转换成机器能看懂的可重定位的二进制代码
4.链接:链接代码中调用的库

用代码解释编译过程

在这里插入图片描述
用gcc直接编译这个test.c文件会直接生成一个可执行程序
在这里插入图片描述
-o指定生成文件的名字
在这里插入图片描述
-E选项,只执行编译的第一步:预处理,预处理后的文件通常用i作为后缀。
在这里插入图片描述在这里插入图片描述
在底行输入vs test.c,可以同时看两个文件,使用ctrl+w+w,光标在两个分屏窗口切换

可以看到头文件被展开,宏替换,去注释,条件编译后生成的预处理文件
在这里插入图片描述
-S选项,对i文件进行编译生成汇编代码,文件通常以s作为后缀。
在这里插入图片描述
s文件中都是汇编代码
在这里插入图片描述
-c选项,对s文件进行汇编,生成机器能看懂的二进制文件在这里插入图片描述
od -x xxx,xxx是文件名,这是查看二进制文件的指令。编译后的一部分代码就如上图所示。在这里插入图片描述
在这里插入图片描述
此时的test.o还不能执行(连执行属性都没有),强行加上后又说不能执行该二进制文件。原因是生成可执行程序还差最后一步:链接,代码中包含了头文件。头文件只是声明了有这个方法可以使用,但这个方法的具体实现在库中(可以将库理解为特殊处理过的源文件),链接就是将库与代码产生联系(链接起来)在这里插入图片描述

使用gcc直接对文件进行操作,gcc指令中默认会将文件与库进行链接,此时的out文件就是可执行文件在这里插入图片描述

动态库与静态库概念

动态库后缀 Linux(.so) windows(.dll)
静态库后缀 Linux(.a) windows(.lib)

由动态库与静态库引出的两个概念:动态链接和静态链接,动态库作为单独文件独立于你的代码文件存在,如果你的代码需要调用动态库,程序会找到动态库的存储位置然后调用里面的函数,一般情况下动态链接较为常见。

而静态链接是将静态库拷贝到你的代码文件中,如果调用的静态库较多,拷贝的代价会很大,你的文件大小也随之增加
在这里插入图片描述
(安装c语言静态库:sudo yum install -y glibc-static,安装c++静态库:sudo yum install -y libstdc++ -static)

静态链接产生的文件大小大概是动态的100倍

gdb的使用

用gcc默认编译的文件版本是release的,release版本不能进行调试,在gcc命令后加上-g选项,编译的版本就是debug,能进行调试的版本。
在这里插入图片描述
test_g.out比test.out多出了一千多字节,这些多出的信息就是文件的调试信息。

调试的相关指令

进入gdb,gdb 文件名(test_g.out),文件必须是-g选项生成的可执行文件
在这里插入图片描述

  • b(break) 行号,打断点
  • info b,查看所有断点信息
  • d 断点编号,删除断点
  • l 行号,显示该行的代码
  • s(step),逐语句,(可以进入函数)
  • n(next),逐过程,(跳过函数)
  • display && undisplay,常显示一个变量的值和取消常显示
  • until 行号,跳转到指定行
  • r,运行程序
  • c(continue),从一个断点运行到另一个断点
  • finish,执行完一个函数就停止
  • quit,退出

(l 0很好用,连续敲回车可以依次查看代码)

makefile/make

(make是一个命令,makefile是一个文件)

vs作为一个集成开发环境,可以不用对每个源文件进行编译,vs会自动编译工程中所有的源文件(ctrl + B自动编译),但linux中的工程,如果源文件的数量较多,在该工程中应该先编译哪个源文件?整个工程的结构应该是怎样的?使用Linux的编译器就会面临这样的问题,Linux提供了一个工具makefile,该工具能解决整个工程的编译问题。

makefile的目的是编译文件,要达到这个目的需要告知源文件和可执行文件之间的依赖关系,以及源文件生成可执行文件的依赖方法。

所以makefile中要写依赖关系和依赖方法,比如test.out依赖test.c生成,要生成这个可执行文件的依赖方法是gcc test.c -o test.out,

在这里插入图片描述
第一行的依赖关系,test.out依赖test.c生成,

  • 格式为目标文件:依赖文件

第一行就是test.out:test.c,第二行要先敲一个Tab,接着是编译该可执行文件的指令,比如gcc test.c -o test.out。
在这里插入图片描述
PHONY是一个关键字,.PHONY:后跟一个伪目标,也就是说使用make命令后,系统不会生成这个目标文件,因为它是伪目标,声明完伪目标后,由于clean **“文件”**没有依赖文件,所以clean的冒号后为空,定义完目标文件clean后,回车Tab写上删除文件的指令。(rm -f删除文件,如果文件不存在不输出提示信息)

要删除生成的可执行文件就敲make clean命令
在这里插入图片描述
被.PHONY修饰的伪目标,表示该依赖关系总是被执行,何为总是被执行?无论目标文件是否新旧,直接执行依赖关系
在这里插入图片描述
clean是.PHONY修饰的伪目标,用make clean执行依赖关系:rm -f test.out时,由于系统不会伪目标,所以系统执行make clean时,检测到makefile的同级目录下没有该目标文件,所以总是指向伪目标的依赖方法。而make生成的目标文件test.out没有被.PHONY修饰,make生成了目标文件后,再次make,系统检测到test.out是新生成的文件,并且其依赖文件的没有更新,所以不会执行gcc test.c -o test.out这个依赖关系。
在这里插入图片描述
还有一点,make只会生成第一个目标文件,执行该依赖关系的依赖方法。如果clean写在test可执行文件前面,make就只会clean在这里插入图片描述
最后,可以用$@, $^简化书写

  • $@表示目标文件, $^表示依赖文件
  • 如果依赖文件不止一个,那么$^表示所有的依赖文件
test.out:test.c
	gcc $@ -o $^

可以用这两个符号写makefile文件

目标文件的新旧,系统是怎样分别的?

通过时间来区别文件的新旧,Linux中的文件由内容和属性组成,使用stat命令显示文件的状态信息,可以看到文件有三个时间

  • Access:文件的访问时间,如果进入该文件达到一定的次数这个时间会更新
  • Modify:文件的内容被修改,时间更新
  • Change:文件的属性被修改,时间更新

但修改了文件的内容,Modify时间一定改变,而修改内容可能改变文件的属性,所以Change时间也可能改变
在这里插入图片描述比如test.c生成目标文件test.out,那么test.c的修改时间一定先于test.out,但修改了test.c,test.c的修改时间就会改变。使用make命令时,如果test.c的修改时间后于目标文件test.out,那么make会执行依赖关系gcc test.c -o test.out,如果依赖的修改时间先于目标文件,那么make不会指向依赖关系

makefile的多文件使用

在这里插入图片描述
在这里插入图片描述
解析一下makefile的逻辑:现在有两个源文件hello.c和main.c,将这两个源文件编译成hello.o和main.o目标文件后,将这两个目标文件作为新的目标文件hello的依赖文件进行编译

clean:清理目标文件,将所有以.o结尾的文件清理,以及hello这个可执行文件

缓冲区理解

在这里插入图片描述
这段代码是先输出hello world再休眠还是先休眠在输出hello world?由于缓冲区的存在,程序的结果是先睡眠再输出。因为缓存区是一段内存,缓冲区采用的刷新策略是行刷新,当缓冲区没有满或者一行没有结束时,缓冲区的内容不会向显示器输出。如果在hello world后加上\n,就会先打印hello world,再睡眠。

进度条的打印

在这里插入图片描述
进度条运行的效果
在这里插入图片描述
%-100s,打印字符串,预留100个字符的空间,-的意思是让打印内容从左向右填充。

后面是一个旋转的特效,依次定义plan中的每个字符,为了保证不越界,cnt要%4。

plan中要用\表示\,因为\是一个转义字符。

但这段代码最重要的一部分是fflush(stdout),将缓存区的内存向标准输出流中输出,也就是输出到屏幕,每次进度条变化都要刷新缓冲区,否则这个效果就会一卡一卡的(但同样的代码在vs下,不加fflush却不会造成卡顿,这说明vs和gcc的缓冲区刷新机制不同,vs是直接输出,gcc则是达到缓冲区满了再输出)。

git使用

用git clone xxx将远程仓库克隆到本地,xxx是仓库的网址。用git上传代码的三板斧:git add xxx,xxx是文件名,add之后git commit -m “xxx”,xxx是这次提交的日志,,最后是git push,将提交的代码上传到远程仓库里。

当仓库的代码需要更新时,使用git pull拉取最新的代码。
在这里插入图片描述
git status,查看这次提交的文件
在这里插入图片描述
.gitignodre文件里存储的是git提交可以忽略的文件后缀,即带有该后缀的文件不会被上传,是一个黑名单文件。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值