What is it when printf () is sending output to a buffer?

I am experiencing "C PRIMER PLUS" and there is this topic about "OUTPUT FLUSHING". Now he says:

Operators

printf()

send the output to an intermediate storage called a buffer. From time to time, material in the buffer is sent to the screen. The standard C rules for when output is sent from the buffer to the screen is clear:

  • It is sent when the buffer is full.
  • When a newline character is encountered.
  • At the impending entrance.

(Sending output from a buffer to a screen or file is called flushing the buffer.)

Now to check the above statements. I wrote this simple program:

#include<stdio.h>

int main(int argc, char** argv) {

printf("Hello World");

return 0;
}

      

So neither printf () contains a newline, or it has some kind of pending input (like a scanf () statement or any other input statement). Then why is it printing the content to the output screen.

Suppose the first condition is true. The buffer is full (which cannot happen at all). With this in mind, I was truncating the statement inside printf () to

printf("Hi");

      

However, it prints the instruction to the console.

So what is the deal, all of the above conditions are false, but still I get the output on the screen. Can you tell us in detail. It looks like I'm getting the concept wrong. Any help is appreciated.

EDIT: As suggested by a very helpful comment, perhaps executing the exit () function after the program finishes causing all buffers to be flushed, resulting in output to the console. But then if we hold the screen before executing exit (). Like this,

#include<stdio.h>

int main(int argc, char** argv) {

printf("Hello World!");
getchar();

return 0;
}

      

It is still being output to the console.

+3


source to share


2 answers


Output buffering is an optimization technique. Writing data to some devices (fe hard drives) is an expensive operation; why buffering appeared. Essentially, it avoids writing data byte-by-byte (or char -by-char) and concatenates it into a buffer to write multiple KiBs of data at once.

As an optimization, the output buffering should be transparent to the user (it's transparent even to the program). This should not affect the behavior of the program; with or without buffering (or with different buffer sizes), the program should behave the same. This is what you were talking about.

A buffer is only an area of ​​memory in which data to be written is temporarily stored until enough data has been accumulated to make the writing process to the device efficient. Some devices (hard disk, etc.) do not even allow writing (or reading) data in small chunks, but only in blocks of a certain fixed size.

Buffer wash rules:

  • It is sent when the buffer is full.

It is obvious. The buffer is full, its purpose is fulfilled, let the data be transferred to the device. Also, there is probably more data coming from the program, we need to free up some space.

  1. When a newline character is encountered.

There are two types of devices: linear and block. This rule applies only to line mode devices (eg, a terminal). It doesn't make sense to flush the buffer on line wrapping when writing to disk. But it makes sense to do this when the program is writing to the terminal. In front of the terminal, the user eagerly awaits the exit. Don't let them wait too long.



But why does output to the terminal need buffering? Writing on the terminal is not expensive. This is correct when the terminal is physically located near the processor. Not also when the terminal and the processor are halfway across the globe and the user is running the program over a remote connection.

  1. At the impending entrance.

He should read "when there are barriers to input on one device" for it to be clarified.

Reads are also buffered for the same reason as writing: efficiency. The reading code uses its own buffer. It fills the buffer as needed, then scanf()

, and the other I / O functions get their data from the input buffer.

When the input is to happen on the same device, the buffer must be flushed (data actually written to the device) to ensure consistency. The program sends some data to the output, and now it expects it to return the same data; why the data has to be flushed to the device for the read code to find it and load it.

But why are the buffers flushed when the application exits?

Err ... buffering is transparent, it shouldn't affect application behavior. Your application has sent some data to the exit. The data should be there (on the output device) when the application exits.

Buffers are also flushed when associated files are closed for the same reason. And this is what happens when the application exits: the cleanup code closes all open files (standard input and output are just files from the application's point of view), closing the forces flushing the buffers.

+2


source


Part of the specification exit()

in the C standard (POSIX reference):

Then all open streams with unwritten buffered data are flushed, all open streams are closed, ...

This way, when the program exits, the pending output is flushed, regardless of newlines, etc. Likewise, when the file is closed ( fclose()

), the pending output is written:

Any unwritten buffered data for the stream is delivered to the host environment for writing to a file; any unread buffered data is discarded.

And, of course, the function fflush()

flushes the output.

The rules mentioned in the question are not entirely accurate.



  • When the buffer is full, that's right.

  • When a newline is encountered, this is incorrect, although it is often used. If the output device is an "interactive device" then line buffering is used by default. However, if the output device is "non-interactive" (disk file, pipe, etc.), then the output is not necessarily (or usually) line buffered.

  • When input is pending, this is also incorrect, although it usually works. Again, this depends on whether the input and output devices are "interactive".

The output buffering mode can be changed by calling setvbuf()

to set buffering, line buffering, or full buffering.

The standard says (§7.21.3):

¶3 When the stream is unbuffered, characters should appear from both source and destination as soon as possible. Otherwise, characters can accumulate and be transferred to or from the host environment as a block. When a stream is fully buffered, characters are intended to be sent to or from the host environment as a block when the buffer is full. When a stream is line buffered, characters are intended to be sent to or from the host environment as a block when a newline character is encountered. In addition, characters are intended to be sent as a block to the host environment when a buffer is full, when input is requested on an unbuffered stream, or when a request is requested on a buffered stream that requires characters to be sent from the host environment. Support for these characteristics is implementation-defined and may be affected from using functionssetbuf

and setvbuf

.

...

¶7 When the program starts, three text streams are predefined and do not explicitly need to be opened - standard input (to read normal input), standard output (to write normal output) and standard error (to write diagnostic output). As originally discovered, standard error is not fully buffered; standard input and standard output streams are fully buffered if and only if you can define a stream so as not to refer to an interactive device.

Also, in §5.1.2.3 Program Execution says:

  • The dynamics of input and output of interactive devices shall take place as specified in 7.21.3. The goal of these requirements is to have unbuffered or string output as soon as possible, to ensure that the request messages are actually displayed before the program expects input.
+2


source







All Articles