What are the rules of automatic stdout buffer flushing in C?
I'm just curious which conditions should be satisfied to flush stdout buffer automatically.
First of all I was confused that this pseudo code doesn't print output every iteration:
while (1) {
printf("Any text");
sleep(1);
}
But if I add newline character it will.
After few experiments i found that on my machine stdout buffer is flushed:
- When I put to stdout 1025 characters or more;
- When I read stdin;
- When I put newline character to stdout;
The first condition is totally clear - when the buffer is full it should be flushed. The second one is also reasonable. But why newline character causes flushing? What are the others implicit conditions for this?
Solution 1:
Rules of automatic flushing stdout buffer is implementation-defined (ID). It is ID when the stream is unbuffered, fully buffered, or line buffered.
When a stream is unbuffered, characters are intended to appear from the source or at the destination as soon as possible. Otherwise characters may be accumulated and transmitted to or from the host environment as a block.
When a stream is fully buffered, characters are intended to be transmitted to or from the host environment as a block when a buffer is filled.
When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered. Furthermore, characters are intended to be transmitted as a block to the host environment when a buffer is filled, when input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment.
Support for these characteristics is implementation-defined, ... C11dr §7.21.3 3
I'm just curious which conditions should be satisfied to flush stdout buffer automatically.
If code wants to insure output is certainly flushed, use fflush()
. Other conditions that may automatically flush the stream are implementation defined.
Solution 2:
A output stream which is line-buffered shall be flushed whenever a newline is output.
An implementation may (but is not required to) flush all line-buffered output streams whenever a read is attempted from any line-buffered input stream.
Implementations are not allowed to make streams fully-buffered by default unless it can be determined that they are not associated with an "interactive device". So when stdin/stdout are terminals they can't be fully-buffered, only line-buffered (or unbuffered).
If you only need flushing when the output is to a terminal, it suffices to assume that writing a newline results in flushing. Otherwise you should explicitly call fflush
wherever you need flushing.
Solution 3:
See the man page for setbuf(3)
. By default, stdout
is set to line buffering mode.
printf()
and its variants work with buffered output, and delegate to write()
. So this buffering is controlled by the C library implementation of printf
, with the buffer and buffer settings located in the FILE
structure.
It's also worth noting the difference between section 3 and section 2 of the unix man pages. Section 2 is made up of function calls that directly talk to the operating system and do things that it would otherwise be impossible to do from a pure user program. Section 3 is made up of function calls that a user could reproduce on their own, which often delegate to section 2 calls. Section 2 functions contain the low-level "magic" that allow C programs to interact with the outside world and perform I/O. Section 3 functions can provide a more convenient interface to the section 2 functions.
printf
, scanf
, getchar
, fputs
, and other FILE *
functions all are section 3 functions that delegate to write()
and read()
, which are section 2 functions. read()
and write()
do not buffer. printf()
interacts with the buffer in the FILE
structure, and occasionally decides to send the contents of that buffer out through write()
.