Linux printf函数输出问题

1.printf函数并不会直接将数据输出到屏幕,而是先放到缓冲区中。

原因是:
解决效率和性能的问题。

比如说,printf在打印数据到屏幕上的时候不经过缓冲区,而是直接调用内核,此时内核就相当于另外一个进程,这时候就意味着想让内核帮printf做打印这件事,那么把所要打印的数据交给了内核,那么在提交这个操作以后,内核就要代表printf去执行这个操作,此时会发生阻塞,这个阻塞其实就是会发生一个从用户态到内核态的切换,切换之后内核帮printf把事情做完,然后再回复程序的执行。如果是这样的话,就相当于每次执行printf都会发生一个从用户态到内核态的切换,也就是说当前程序的执行会发生一个切换,把内核切换上来去执行,用户随便去执行printf进行打印会导致程序不断在用户态和内核态之间切换,因为从用户态到内核态的切换有很大的开销,所以频繁的切换会导致效率和性能不好。

那么,printf在打印数据到屏幕上的时候把数据先放到缓冲区,当缓冲区被放满了,这个时候再把所要打印的数据提交给内核,从用户态切换到内核态,这时候这个切换就只有一次。这样做的弊端是当执行了printf之后,所要打印的数据不能及时被打印到屏幕上,必须等缓冲区放满、或者用户强制刷新缓冲区或者程序结束才能将数据打印到屏幕上。

2.只有以下三种情况满足,才会将结果输出屏幕

(1)缓冲区满
假设现在要输出的内容有很多,当要执行printf输出内容的时候把这些内容都放到了缓冲区中,再执行printf输出内容的时候把这些内容继续放到了缓冲区中,等缓冲区的数据放满以后,才会把缓冲区中的数据提交给内核,内核调用底层的驱动程序将数据打印到屏幕上。

(2)强制刷新缓冲区

(3)程序结束时

3.示例

(1)等程序结束时将结果输出到屏幕

代码如下图所示:
在这里插入图片描述

退出vi编译并执行代码:

在这里插入图片描述

在等待3秒程序结束之后才会将"hello"打印到屏幕上:

在这里插入图片描述

在上述例子中,程序先执行了printf函数把数据"hello"放到了缓冲区中,缓冲区当前无法把数据提交给内核进行打印,睡眠3秒,3秒之后程序结束,程序结束的时候会刷新缓冲区,这时候缓冲区有多少数据就打印多少数据。

执行exit(0)退出程序,首先就是去刷新缓冲区,然后才退出程序。在执行exit(0)刷新完缓冲区之后再调用_exit(0)才会真正退出一个进程。也就是说执行exit(0)刷新缓冲区,然后exit(0)去调用_exit(0),这时候程序才会真正结束。

假如将代码中的exit(0)改为_exit(0),那么在编译执行程序的时候程序会直接结束,屏幕上不会输出任何数据,这就是因为直接使用_exit(0)的时候没有刷新缓冲区,而是直接退出程序。

(2)刷新缓冲区

①通过"\n"刷新缓冲区:

代码如下所示:

在这里插入图片描述

退出vi编译并执行代码:

在这里插入图片描述

在等待3秒之后程序结束:

在这里插入图片描述

②通过fflush()刷新缓冲区

fflush()函数的原型:

fflush(FILE *stream);

参数的类型是FILE*类型,比如stdin、stdout、stderr。

代码如下所示:

在这里插入图片描述

退出vi编译并执行代码:

在这里插入图片描述

在等待3秒之后程序结束:

在这里插入图片描述

在"hello"被打印出来之后,会刷新缓冲区,程序结束。

以上两种刷新缓冲区的方法,需要连续打印不可以换行的时候用fflush(),不需要连续打印就用"\n"。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值