Extremely Buffered Output

A few weeks back, I wrote a post on the fflush() function, which immediately relieves an output buffer, releasing its contents. The mirror opposite of this function might be another output control function, setbuf().

To understand what setbuf() does, as well as fflush(), I must blather on about how output buffering works in C.

<blather>
For text output, C uses three types of buffering: unbuffered, block buffered, and line buffered. You’ve probably seen this type of buffering in action, but didn’t recognize what it was or that clever terms existed to describe it.

Unbuffered output is generated as soon as it’s written. The characters aren’t stored.

Block buffered output implies that characters are stored in a buffer. When the buffer gets full, its contents are dumped en masse to the output device. The buffer is also dumped by an fflush() statement or when closing the output device, such as a file.

Line buffered output works like block buffered, though when a newline is encountered, the buffer is output.

In C, file output is block buffered. Output to stdout is line buffered. The stderr device is unbuffered.
</blather>

The setbuf() function alters buffering behavior for an output device, stdout or an open file handle. Here’s the format:

void setbuf(FILE *restrict stream, char *restrict buf);

The stream argument is a FILE handle or stdout for the standard output stream. The second argument, buf, is a character buffer set to the size BUFSIZ. The BUFSIZ defined constant is set in the stdio.h header. If you want to set a different size, use the setbuffer() function instead, where the third argument sets the buffer’s size.

The following code demonstrates how each line sent to standard output is line-buffered. The getchar() function pauses output, then the final line is sent.

#include <stdio.h>

int main()
{
    puts("Hold it!");
    puts("Hold it!");
    puts("Go!");
    getchar();
    puts("Thank you.");

    return(0);
}

Here’s the output:

Hold it!
Hold it!
Go!

(Enter is pressed.)
Thank you.

In this modification to the code, the setbuf() function activates blocked buffering for standard output, holding all text sent to stdout until the program stops (or the buffer fills):

#include <stdio.h>

int main()
{
    char buffer[BUFSIZ];

    /* setup the buffer */
    setbuf(stdout,buffer);

    puts("Hold it!");
    puts("Hold it!");
    puts("Go!");
    getchar();
    puts("Thank you.");

    return(0);
}

The setbuf() function at Line 8 redirects output to stdout to the buffer declared at Line 5. Output waits until the buffer is full, the buffer is flushed, or in this case when the program stops:

(Enter is pressed.)
Hold it!
Hold it!
Go!
Thank you.

If you’re a Unix nerd, I recommend you read the documentation in the man page for setbuf(). It’s interesting to see how file I/O can be manipulated. Further, you can set an environment variable to control buffering in the terminal window. It’s pretty cool stuff, nerdy, but good.

Leave a Reply