Question

int main()
{
    printf("Hello"); // doesn't display anything on the screen

    printf("\n"); // hello is display on the screen

    return 0;
}

All characters(candidate of printing) are buffered until a new line is received? Correct?

Q1 - Why does it wait before printing on terminal until a newline char?

Q2 - Where are the characters of first printf (i.e. "Hello") buffered?

Q3 - What is the flow of printing printf()->puts()->putchar() -> now where? driver? Does the driver has a control to wait until \n?

Q4 - What is the role stdout that is attached to a process?

Looking for a in-depth picture. Feel free to edit the question, if something doesn't makes sense.

Was it helpful?

Solution

I'll start with some definitions and then go on to answer your questions.

File: It is an ordered sequence of bytes. It can be a disk file, a stream of bytes generated by a program (such as a pipeline), a TCP/IP socket, a stream of bytes received from or sent to a peripheral device (such as the keyboard or the display) etc. The latter two are interactive files. Files are typically the principal means by which a program communicates with its environment.

Stream: It is a representation of flow of data from one place to another, e.g., from disk to memory, memory to disk, one program to another etc. A stream is a source of data where data can be put into (write) or taken data out of (read). Thus, it's an interface for writing data into or reading data from a file which can be any type as stated above. Before you can perform any operation on a file, the file must be opened. Opening a file associates it with a stream. Streams are represented by FILE data type defined in stdio.h header. A FILE object (it's a structure) holds all of the internal state information about the connection to the associated file, including such things as the file position indicator and buffering information. FILE objects are allocated and managed internally by the input/output library functions and you should not try to create your own objects of FILE type, the library does it for us. The programs should deal only with pointers to these objects (FILE *) rather than the objects themselves.

Buffer: Buffer is a block of memory which belongs to a stream and is used to hold stream data temporarily. When the first I/O operation occurs on a file, malloc is called and a buffer is obtained. Characters that are written to a stream are normally accumulated in the buffer (before being transmitted to the file in chunks), instead of appearing as soon as they are output by the application program. Similarly, streams retrieve input from the host environment in blocks rather than on a character-by-character basis. This is done to increase efficiency, as file and console I/O is slow in comparison to memory operations.

The C library provides three predefined text streams (FILE *) open and available for use at program start-up. These are stdin (the standard input stream, which is the normal source of input for the program), stdout (the standard output stream, which is used for normal output from the program), and stderr (the standard error stream, which is used for error messages and diagnostics issued by the program). Whether these streams are buffered or unbuffered is implementation-defined and not required by the standard.

GCC provides three types of buffering - unbuffered, block buffered, and line buffered. Unbuffered means that characters appear on the destination file as soon as written (for an output stream), or input is read from a file on a character-by-character basis instead of reading in blocks (for input streams). Block buffered means that characters are saved up in the buffer and written or read as a block. Line buffered means that characters are saved up only till a newline is written into or read from the buffer.

stdin and stdout are block buffered if and only if they can be determined not to refer to an interactive device else they are line buffered (this is true of any stream). stderr is always unbuffered by default.

The standard library provides functions to alter the default behaviour of streams. You can use fflush to force the data out of the output stream buffer (fflush is undefined for input streams). You can make the stream unbuffered using the setbuf function.

Now, let's come to your questions.

Unmarked question: Yes, becausestdout normally refers to a display terminal unless you have output redirection using > operator.

Q1: It waits because stdout is newline buffered when it refers to a terminal.

Q2: The characters are buffered, well, in the buffer allocated to the stdout stream.

Q3: Flow of the printing is: memory --> stdout buffer --> display terminal. There are kernel buffers as well controlled by the OS which the data pass through before appearing on the terminal.

Q4: stdout refers to the standard output stream which is usually a terminal.

Finally, here's a sample code to experiment things before I finish my answer.

#include <stdio.h>
#include <limits.h>

int main(void) {
    // setbuf(stdout, NULL);     // make stdout unbuffered
    printf("Hello, World!");     // no newline
    // printf("Hello, World!");  // with a newline

    // only for demonstrating that stdout is line buffered

    for(size_t i = 0; i < UINT_MAX; i++)
        ;                        // null statement

    printf("\n");                // flush the buffer
    return 0;
}

OTHER TIPS

printf is not writing directly to the screen, instead it writes to the output stream, which is by default buffered. The reason for this is, that there may not even be a screen attached and the output can go to a file as well. For performance reasons, it is better for a system if access to disc is buffered and then executed in one step with appropriately sized chunks, rather than writing every time.

You can even change the size of the buffer and set it to 0, which means that all output goes directly to the target, which may be usefull for logging purposes.

setbuf(stdout, NULL);

The buffer is flushed either when it is full, or if certain criterions are fullfilled, like printing a newline. So when you would execute the printf in a loop, you would notice that it will write out in chunks unless you have a newline inbetween.

Yes, by default, standard output is line buffered when it's connected to a terminal. The buffer is managed by the operating system, normally you don't have to worry about it.

You can change this behavior using setbuf() or setvbuf(), for example, to change it to no buffer:

setbuf(stdout, NULL);

All the functions of printf, puts, putchar outputs to the standard output, so they use the same buffer.

If you wish, you can flush out the characters before the new line by calling

fflush(stdout);

This can be handy if you're slowly printing something like a progress bar where each character gets printed without a newline.

int main()
{
    printf("Hello"); // Doesn't display anything on the screen
    fflush(stdout);  // Now, hello appears on the screen
    printf("\n");    // The new line gets printed
    return 0;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top