●个人主页:你帅你先说.
●欢迎点赞关注收藏
●既选择了远方,便只顾风雨兼程。
●欢迎大家有问题随时私信我!
●版权:本文由[你帅你先说.]原创,CSDN首发,侵权必究。
- 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序.
- 但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包>(可以理解成windows上的安装程序)放在一个服务器上, 通过包管理器可以很方便的获取到这个编译好的>软件包, 直接进行安装.
- 软件包和软件包管理器, 就好比 “App” 和 “应用商店” 这样的关系.
- yum(Yellow dog Updater, Modified)是Linux下非常常用的一种包管理器. 主>>要应用在Fedora, RedHat, Centos等发行版上.
Linux下有三种安装软件的方式:
1.源码安装
2.rpm(已经编译的软件包)安装
3.yum安装
我们在安装时可能会存在软件之间的依赖关系,安装非常麻烦,所以前两种方法我们通常不使用,而是使用第三种方法安装,yum
本身会考虑依赖关系。
在手机上我们需要下载软件可以从应用商店里搜索对应软件,Linux上也有这种应用商店
。
在Linux中输入yum list
就会列出linux上能安装的所有软件。
找到对应的软件名然后
yum install xxx
软件就安装上了
如果不想要这个软件了,可以
yum remove xxx
这样软件就卸载了。
vim的三种模式(其实有好多模式,目前掌握这3种即可),分别是命令模式(command mode)、插 入模式(Insert mode)和底行模式(last line mode)。
$ vim test.c
光标相关
k(上)j(下)h(左)l(右)
shift + ^(跳到行首)
shift + $(跳到行尾)
gg(跳到始行)
shift + g(跳到结束行)
n + shift + g(跳到第n行)
b/w:按照单词为单位进行前后光标移动
文本操作:
yy:复制当前行
nyy:复制当前行及其之后的n行,包括当前行
u:撤销误操作
p:粘贴
np:一次重复粘贴n行
dd:删除当前光标所在行,支持ndd
dd->p:剪切功能
shift + ~:快速切换大小写
x:从左向右删除光标之后的一个字符,支持nx
X:从右向左也是支持nX
r:替换一个字符,光标所在的字符,支持nr
shift + r:替换模式,直接进行多个内容的替换
ctrl+r:撤销最近的撤销
ctrl + v:进入visual模式,可通过kj选中多行进行缩进(>向后,<向前),也可多行注释,选中后按I
,然后输入注释符,再按esc退出(这步很关键),以C/C++为例就是//
。
底行模式
set nu:调出行号
set nonu:取消行号
w:保存
q:退出
!:强制操作
C语言阶段,我们学过程序执行过程的几个阶段。
- 预处理(进行宏替换)
- 编译(生成汇编)
- 汇编(生成机器可识别代码)
- 连接(生成可执行文件或库文件)
在Linux中,我们可以查看预处理的过程
gcc -E test.c -o mytest.i
//开始进行翻译(四个过程统称为翻译),完成预处理之后,停下来,把预处理的结果放入mytest.i文件
gcc -S test.i -o test.s
gcc -c test.s -o test.o
打开后你会发现全是乱码。这是因为不是以二进制的形式打开的,但这些都不重要。汇编形成的二进制文件,并不可以直接执行,它是一种可重定向目标文件。
计算机可以直接执行汇编语言吗?汇编语言需要编译吗? 不可以。需要。
我们知道,每个语言都有自己的库(一套头文件+一套库文件(libc.a,libc.so))。程序通过链接来将我们自己代码中的函数调用,外部数据和库关联起来。
查看链接过程
gcc -c mytest.s -o mytest.o
相信有人会有疑问,为什么C程序的翻译是这个过程?
我们早期编程使用的是二进制编程(打孔编程)
后面人们发现用二进制编程效率实在是太低了,所以就有了汇编语言(助记符),但汇编语言最终还是得翻译成二进制,所以就有了编译器,但汇编语言相对来说还是太复杂了,所以C语言就诞生了。
我们要如何理解链接?
Linux中有静态库(.a)和动态库(.so),它们都与程序能否成功运行有关,所以链接过程其实就是程序与第三方库提供的方法关联起来。链接中又分为静态链接和动态链接。动态链接简单来说就是,比如你执行程序,你需要调用库函数printf,然后程序就会和库建立联系,在库中执行然后再把结果返回给程序。静态链接就是把库中的代码直接拷贝进我的可执行程序中。
通过命令显示,我们发现gcc默认采用动态链接方式,形成可执行程序。
g++的基本操作和gcc基本一样,在这里不再赘述。
我们知道,C++是兼容C的,所以g++也可以编译C语言程序,但一般我们不建议这样做。
在学习C/C++中,如果代码有问题,我们可以设断点调试,在Linux中,如果说vim
是编译器,那么gdb
就是调试器。
gdb 文件名
- list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
- list/l 函数名:列出某个函数的源代码。
- r或run:运行程序。
- n 或 next:单条执行。
- s或step:进入函数调用
- break(b) 行号:在某一行设置断点
- break函数名:在某个函数开头设置断点
- info break :查看断点信息。
- finish:执行到当前函数返回,然后停下来等待命令
- print( p ):打印表达式的值,通过表达式可以修改变量的值或者调用函数
- p 变量:打印变量值。
- set var:修改变量的值
- continue(或c):从当前位置开始连续而非单步执行程序
- run(或r):从开始连续而非单步执行程序
- delete breakpoints:删除所有断点
- delete breakpoints n:删除序号为n的断点
- disable breakpoints:禁用断点
- enable breakpoints:启用断点
- info(或i) breakpoints:参看当前设置了哪些断点
- display 变量名:跟踪查看一个变量,每次停下来都显示它的值
- undisplay:取消对先前设置的那些变量的跟踪
- until X行号:跳至X行
- breaktrace(或bt):查看各级函数调用及参数
- info(i) locals:查看当前栈帧局部变量的值
- quit:退出gdb
这个时候还不能调试,如果你输入命令,它会报错
为什么会报错?
因为如果一个程序是可以被调试的,该程序的二进制文件一定加入了一些debug信息。
我们C语言阶段介绍过程序有debug版本和release版本,release版本会比debug版本更小,就是因为release版本没有加入调试信息。这样我们就理解了,Linux中形成的程序默认情况下是release版本。
添加调试信息
gcc test.c -o test -g
现在程序就可以调试了。
如果你是在for循环里定义变量,可能程序会报错,因为这种写法是从C99开始的。
这时候只需要在原来命令后面加一个-std=c99
。
-g
也要加,不加不能调试。
以下命令只在调试模式下有效
打断点
b 行号
显示断点
info b
删除断点
d 行号
禁用断点
disable 行号
启用断点
enable 行号
逐过程调试
n
显示值
display 变量名
删除监视的变量
undisplay 编号
此时我想删除&sum
这个变量
直接输入变量名是会报警告的,必须是它的编号。
进入函数
s
这个命令类似于vs编译器的逐语句,可以进入函数内部进行调试。
结束函数
finish
这个使用场景就是当你进入了你自定义的函数后,然后你想退出就可以敲这个命令。
到达下一个断点
continue
跳到某行
until 行号
查看调用堆栈
bt
- 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
- 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
- makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编 译,极大的提高了软件开发的效率。
- make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
- make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
先创建一个Makefile
文件,输入图中的命令。
然后make
然后你就发现里面写的命令被执行了。
还可以再写一条清楚可执行程序的命令。
然后make clean
可执行文件就被删除了。
可能有人会疑问,为什么生成可执行程序只需要一个make
,而删除却要make clean
?
因为make扫描Makefile文件的时候,默认只会形成一个目标依赖关系,一般是第一个。
也就是说如果你把clean的命令写在前面,再make就会执行刚刚rm -f test
的操作。
.PHONY:
是一个伪目标(总是可执行的),修饰对应的符号。
我们发现,make了一次后就无法make了,这是因为系统会去检测你的代码有没有改变,如果没有,就不会重新编译,但如果是一个伪目标,比如刚刚的make clean
,不管执行多少次都可以,因为它总是可执行的。
刚刚的命令还可以简写成
test:test.c
gcc -o $@ $^
$@
代表test
,$^
代表test.c
我们在使用电脑时,经常会说到回车换行
,但你有想过回车
和换行
是两个概念吗?
回车指的是回到当前行的最开始。
换行指的是列不变,新起一行。
我们来看段代码
#include
#include
int main()
{
printf("hello world!");
sleep(5);
return 0;
}
执行这段代码时,你会发现一个你无法理解的现象,程序运行时,并不是马上输出,而是停了一会,那这样是不是说明程序是先执行sleep再执行printf?
显然不是。原因是因为虽然printf已经执行,但是数据没有立即被刷新到显示器当中!
没有’\n’,字符串会暂时保存到C语言级别的缓冲区中,显示器设备的刷新策略就是行刷新,即遇到’\n’才会进行刷新。
C程序,会默认打开三个输入输出流
stdin,stdout,stderr
键盘 显示器 显示器
注意:从显示器上显示的都是字符,从键盘读取的内容也都是字符。
刚刚那段代码想要立即显示,只需要加上
fflush(stdout)
基于以上这些,我们可以写一个小程序
这就实现了一个倒计时功能。
利用上面的思想,我们就可以开始写进度条了。
#include
#include
#include
int main()
{
int i = 0;
char bar[101];
memset(bar,'\0',sizeof(bar)/sizeof(bar[0]));
const char *lable = "|/-\\";
while(i <= 100)
{
bar[i] = '\0';
printf("%s %d%% %c\r",bar,i,lable[i%4]);
fflush(stdout);
bar[i] = '#';
i++;
usleep(50000);//单位是微秒
}
printf("\n");
return 0;
}
这样一个简易的进度条就完成了。
但这样写出来的进度条确实简易,大家可以自行对代码进行完善。
这是博主添加配色后的代码。
#include
#include
#include
int main()
{
int i = 0;
char bar[101];
memset(bar,'\0',sizeof(bar)/sizeof(bar[0]));
const char *lable = "|/-\\";
while(i <= 100)
{
printf("\033[1;32;44m%s\033[0m [%d%%][%c]\r",bar,i,lable[i%4]);
fflush(stdout);
bar[i] = ' ';
i++;
usleep(50000);//单位是微秒
}
printf("\n");
return 0;
}
printf()的配色方案大家可以在网上搜一下,根据需要自行配色。
喜欢这篇文章的可以给个一键三连
点赞关注收藏