What is it with printf() sending output to buffer?

Output buffering is an optimization technique. Writing data to some devices (hard disks f.e.) is an expensive operation; that’s why the buffering appeared. In essence, it avoids writing data byte-by-byte (or char-by-char) and collects it in a buffer in order to write several KiB of data at once.

Being an optimization, output buffering must be transparent to the user (it is transparent even to the program). It must not affect the behaviour of the program; with or without buffering (or with different sizes of the buffer), the program must behave the same. This is what the rules you mentioned are for.

A buffer is just an area in memory where the data to be written is temporarily stored until enough data accumulates to make the actual writing process to the device efficient. Some devices (hard disk etc.) do not even allow writing (or reading) data in small pieces but only in blocks of some fixed size.

The rules of buffer flushing:

  1. It is sent when the buffer gets full.

This is obvious. The buffer is full, its purpose was fulfilled, let’s push the data forward to the device. Also, probably there is more data to come from the program, we need to make room for it.

  1. When a newline character is encountered.

There are two types of devices: line-mode and block-mode. This rule applies only to the line-mode devices (the terminal, for example). It doesn’t make much sense to flush the buffer on newlines when writing to disk. But it makes a lot of sense to do it when the program is writing to the terminal. In front of the terminal there is the user waiting impatiently for output. Don’t let them wait too much.

But why output to terminal needs buffering? Writing on the terminal is not expensive. That’s correct, when the terminal is physically located near the processor. Not also when the terminal and the processor are half the globe apart and the user runs the program through a remote connection.

  1. When there is impending input.

It should read “when there is impeding input on the same device” to make it clear.

Reading is also buffered for the same reason as writing: efficiency. The reading code uses its own buffer. It fills the buffer when needed then scanf() and the other input-reading functions get their data from the input buffer.

When an input is about to happen on the same device, the buffer must be flushed (the data actually written to the device) in order to ensure consistency. The program has send some data to the output and now it expects to read back the same data; that’s why the data must be flushed to the device in order for the reading code find it there and load it.

But why the buffers are flushed when the application exits?

Err… buffering is transparent, it must not affect the application behaviour. Your application has sent some data to the output. The data must be there (on the output device) when the application quits.

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

Leave a Comment