为什么printf在调用后不刷新,除非格式字符串中有换行符?这是POSIX行为吗?如何让printf每次都立即刷新?


当前回答

stdout流在默认情况下是行缓冲的,因此只会在它到达换行符后(或当它被告知时)显示缓冲区中的内容。你有几个选项可以立即打印:

使用fprintf打印到stderrinstead (stderr默认是无缓冲的): fprintf(stderr,“我将立即被打印”); 在需要时使用fflush刷新标准输出: printf("Buffered, will flush "); 。fflush (stdout);//现在打印stdout缓冲区中的所有内容 使用setbuf禁用stdout的缓冲: setbuf (stdout, NULL); 或者使用更灵活的setvbuf: setvbuf(stdout, NULL, _IONBF, 0);

其他回答

默认情况下,stdout是行缓冲,stderr是无缓冲,文件是完全缓冲。

Stdout是缓冲的,因此只在打印换行符后输出。

要获得立即输出,可以:

打印到标准错误。 使stdout无缓冲。

一般有2级缓冲-

1. 内核缓冲区缓存(使读/写更快)

2. I/O库中的缓冲(减少no。系统调用)

让我们以fprintf和write()为例。

When you call fprintf(), it doesn't wirte directly to the file. It first goes to stdio buffer in the program's memory. From there it is written to the kernel buffer cache by using write system call. So one way to skip I/O buffer is directly using write(). Other ways are by using setbuff(stream,NULL). This sets the buffering mode to no buffering and data is directly written to kernel buffer. To forcefully make the data to be shifted to kernel buffer, we can use "\n", which in case of default buffering mode of 'line buffering', will flush I/O buffer. Or we can use fflush(FILE *stream).

现在我们在内核缓冲区中。内核(/OS)希望最小化磁盘访问时间,因此它只读取/写入磁盘块。因此,当发出read()时(这是一个系统调用,可以直接或通过fscanf()调用),内核从磁盘读取磁盘块并将其存储在缓冲区中。之后,数据从这里复制到用户空间。

类似地,从I/O缓冲区接收到的fprintf()数据由内核写入磁盘。这使得read() write()更快。

现在要强制内核启动write(),之后的数据传输由硬件控制器控制,也有一些方法。我们可以在写调用期间使用O_SYNC或类似的标志。或者我们可以使用其他函数,如fsync(),fdatasync(),sync(),让内核在内核缓冲区中有数据时立即启动写操作。

立即刷新调用fflush(stdout)或fflush(NULL) (NULL表示刷新所有内容)。

你可以fprintf到stderr,这是无缓冲的。或者您可以在需要时刷新stdout。或者你可以将stdout设置为unbuffered。