前言:
现在你们对“fflushstdout怎么用”可能比较注意,咱们都需要分析一些“fflushstdout怎么用”的相关文章。那么小编在网上收集了一些对于“fflushstdout怎么用””的相关资讯,希望大家能喜欢,姐妹们快快来了解一下吧!前言
如需获取工程文件,xshell,虚拟机和镜像等,请关注公众号【0与1】,并在后台回复【Linux】
本文接前文:Linux系列_3:编辑器vim与编辑器gcc/g++的使用 。编写代码出现问题时,需要快速找出问题的话就需要用到调试了。Linux下调试时使用的gdb调试器,不像在IDE当中,在Linux调试时使用的依旧是终端,所以这也是使用Linux调试的弊端,不过不用担心,VScode可以帮助解决这个问题,让你在图形界面下轻松调试,详细见VS Code+Vim打造C/C++极致开发环境 。实际开发过程中,我们的工程文件不可能只有零星几个,而在前面的讲述中,可以得知一个程序的编译有很多操作,其中最后一个操作是链接,那么这么多文件应该如何链接,或者说有没有顺序要求,这一切的一切都需要make/makefile(项目自动化构建)的帮助。接着本文还用一个小程序——进度条来结束这两篇关于Linux开发入门的文章,最后本文还提及了如何在Linux下提交自己的代码到GitHub下。
一:Linux调试器-gdb(1)debug与release
程序的发布方式有debug和release两种模式,release没有调试信息,不能进行调试,体积较小,debug携带调试信息,可以进行调试,但是文件较大
Linux中,使用gcc/g++编译的程序,默认使用的是release模式,所以就不能直接使用gdb进行调试。如果想要调试,必须在进行gcc/g++编译时,携带-g选项
如下,同一个文件分别使用debug(带-d的)和release,其中debug的文件大小明显大于release
使用readelf -S命令可以查看debug文件
(2)一起来调试一个程序
如下是一个计算1-100的和的C语言程序,进行编译(不要忘记-g)
1:开启调试
输入gdb [文件名],进入调试状态
2:显示源代码
输入list(简写为l),显示源代码便于观察,每次显示10行,按Enter向下翻输入list n(简写为l n),显示第n-5行第n+5行
3:断点
输入break n(简写为b n),在第n行打上一个断点
输入info b,可以查看断点信息输入d [断点编号],删除对应编号的断点输入disable breakpoint [断点编号],禁用对应编号的断点;输入disable breakpoints,禁用所有断点输入enable breakpoint [断点编号],启用对应编号的断点;输入enable breakpoints,启用所有断点
4:运行程序
①:开启运行
输入run(简写为 r),程序开始运行,如果没有断点将直接输入程序结果,如果有断点,程序将停止到第一个断点处。类似于在VS中,在某行上按下了F5打上了断点,然后再按F5,程序将跳转到此断点处,但还没有执行
②:逐语句,逐过程执行
如上,此时来到一个断点处,类似于VS,你会有两种选择:要么逐语句F10,不进入此函数,直接执行此函数跳到下一行语句,要么逐过程F11进入此函数执行
输入next(简写为n),程序会到下一句,若输入step(简写为s),程序会进入这个函数
③:查看变量
上述程序在运行过程中,若需要查看变量的值,则输入p [变量名]
若需要动态查看变量名,则输入display [变量名],接着再执行程序,程序在执行过程中除显示当前执行的语句外,还会显示执行过程中的变量在动态查看中若不想查看某个变量了,取消的方式和设置的方式稍微有点区别。可以发现设置display后,gdb为每个要展示的变量都设置了相应的编号,所以取消时输入undisplay [变量名所对应的编号];如果要全部取消则直接输入display
④:执行中跳转
上述,进入sum函数,就在不断执行循环,如果临时决定想要跳出这个循环,或者直接到某一行,那么就输入until n,其中n表示行号如果想要从一个断点,跳转到下一个断点,则输入c如果进入了某个函数,想要立即结束掉这个函数直接返回到调用处,则输入finish。
(3)总结-gdb选项
选项
描述
list [行号]
显示源代码
list [函数名]
显示某函数的源代码
run
运行程序
next
逐语句执行
step
进入函数
break [行号]
在某行出设置断点
break [函数名]
在某函数开头设置断点
info break
查看断点信息
finish
结束当前函数,返回调用处
p []变量]
打印变量的值
c
跳转到下一个断点
d [断点编号]
删除对应编号的断点
delete breakpoints
删除所有断点
disable/enable breakpoint [断点编号]
禁用/启用对应编号断点
display [变量名]
跟踪变量,执行时每次都显示
undisplay
取消跟踪
until [行号]
跳转到对应行
quit
退出
二:Linux项目自动化构建工具-Make/Makefile(1)前言
对于一个大型项目,可能会涉及到很多文件,例如头文件,源文件等等。在VS中,我们只需在其设定的目录下,新建对应文件然后进行编写即可,然后按下运行键,只要你的代码没有问题,那么就可以运行出结果。这一切一切的感觉看起来很轻松,但是实则不然,例如首先编译哪个文件,如何链接?这些都是需要考虑的,但是VS作为一个集成开发环境,自然而然帮你做好了这一切,但是在Linux中,这些都是需要自己做的。而正因为做这些很麻烦,且不好理解,所以make,makefile应用而生
make/makefilie:用于在Linux中维护项目文件之间的关系,其中make是一个目录,makefile是一个文件,通常该文件存放于当前工作目录
(2)依赖关系和依赖方法
通俗的来讲依赖关系是指:要生成A就必须先生成B,而依赖方法是指:怎样通过B生成A。
比如前述在gcc编译过程时,这几个文件就存在以下依赖关系和依赖方法(假设由hello.c编译生成hello.exe)
hello.exe依赖hello.o,依赖方法是gcc hello.o -o hello.exehello.o依赖hello.s,依赖方法是gcc hello.s -o hello.ohello.s依赖hello.i,依赖方法是gcc hello.i -o hello.shello.i依赖hello.c,依赖方法是gcc hello.c -o hello.i(3)单文件Makefile
简单其工作过程就是,在同一个目录下,创建一个文件叫做Makefile,然后在该文件内,进行编写,编写的代码反映了上述的依赖关系和依赖方法,然后返回终端通过输入目命令,来执行这个过程。很像Windows中的批处理。
准确来说:make是执行依赖关系和依赖方法的命令,Makefile是维护该机制的文件,Makefile里面保存了项目的依赖结构
如下,创建一个hello.c的文件,并编写简单代码,然后再在相同目录下创建文件Makefile
接着在Makefile编写如下代码,其中各项作用解释于图中。
Makefile编写好之后,在命令行直接使用make,就可以调用这个文件执行操作。下面的两个操作相当于VS中的生成解决方案和清理解决方案。
(4)多文件Makefile
编写一个简单加法程序,两个源文件:main .c,compute .c,一个头文件compute. h,使用Makefile进行编译
首先,编写程序如下编写Makefile如下执行
(5)总结
综上所述,当我们编写好Makefile,然后在终端输入make,make就会在当前目录下寻找名字叫做Makefile的文件,如果找到,它会以该文件中的第一个文件(比如上面的exe文件)作为最终需要生成的文件,如果该文件不存在或者说它依赖的.o文件要比这个.exe文件新,那么它就会执行依赖方法,来生成这个.exe文件,同样的,如果.o文件不存在,那么make就会找这个文件的依赖性,再根据上面的规则走下去。但最终,.c文件和.h文件一定会存在的,于是一层套一层,最终直到生成目标文件。
终极makefile三:小程序:进度条(1)两个问题A:缓冲区问题
有如下代码
#include <stdio.h>#include <unistd.h>int main(){ printf("Hello linux\n"); sleep(3) return 0;}12345678
执行效果如下,可以发现当输出带有\n时,能按照正常的逻辑输出,即先打印再等待
若将代码改为下面这样,去掉\n
#include <stdio.h>#include <unistd.h>int main(){ printf("Hello linux"); sleep(3) printf("\n"); return 0;}123456789
可以发现似乎先执行了sleep,再执行printf
但是任何语言都是自上向下执行的,不会出现胡乱执行的问题,出现这个问题的原因在于缓冲区。
printf在执行时,并不是一下就把语句输出到屏幕上去,而是先输出到缓冲区里,然后等到合适的刷新出现后,就将内容发送到屏幕上去,第一次之所以正常输出,是因为有了\n,这个刷新标志,而第二次之所以没有正常输出,是因为printf没有遇到刷新标志,然后就接着执行sleep,最后遇到return才刷新,自然而然感觉是先刷新后打印了
为了解决这一个问题,可以在printf结束之后,让其强制刷新,即输入fflush(stdout),即强制刷新屏幕
#include <stdio.h>#include <unistd.h>int main(){ printf("Hello linux"); fflush(stdout); sleep(3) printf("\n"); return 0;}12345678910(B)回车与换行
转义字符\r表示回车,回车的意思是回到本行的第一个字符处
转义字符\n表示换行,换行的意思是到下一行对应位置再输入
(2)进度条
效果
代码
#include "bar.h" 4 void bar() 5 { 6 char bar[NUM]; 7 memset(bar,'\0',sizeof(bar)); 8 9 const char* label="|/-\\"; 10 int i=0; 11 while(i<100) 12 { 13 fflush(stdout); 14 bar[i++]='#'; 15 usleep(150000); 16 printf("[%-100s][%3d%%][%c]\r",bar,i,label[i%4]); 17 } 18 printf("\n"); 19 }123456789101112131415161718四:Git
如何在Linux上使用GitHub托管代码
按照正常步骤,在GitHub上创建一个代码仓库,复制https
使用git clone,在本地创建相应的一个仓库
需要的代码,拷贝到这个仓库里三板斧之第一板斧–git add。输入git add [文件名]三板斧之第二板斧-git commit。输入git commit三板斧之第三板斧-git push。输入git push,然后输入用户名和密码即可
标签: #fflushstdout怎么用