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

Viewed 7762

I am going through "C PRIMER PLUS" and there is this topic about "OUTPUT FLUSHING". Now it says:

printf() statements sends output to an intermediate storage called buffer. Every now and then, the material in the buffer is sent to the screen. The standard C rules for when output is sent from the buffer to the screen are clear:

  1. It is sent when the buffer gets full.
  2. When a newline character is encountered.
  3. When there is impending input.

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

Now, To verify the above statements. I wrote this simple program :

#include<stdio.h>

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

printf("Hello World");

return 0;
}

so, neither the printf() contains a new line, nor it has some impending input(for e.g. a scanf() statement or any other input statement). Then why does it print the contents on the output screen.

Let's suppose first condition validated to true. The buffer got full(Which can't happen at all). Keeping that in mind, I truncated the statement inside printf() to

printf("Hi");

Still it prints the statement on the console.

So whats the deal here, All of the above conditions are false but still I'm getting the output on screen. Can you elaborate please. It appears I'm making a mistake in understanding the concept. Any help is highly appreciated.

EDIT: As suggested by a very useful comment, that maybe the execution of exit() function after the end of program is causing all the buffers to flush, resulting in the output on the console. But then if we hold the screen before the execution of exit(). Like this,

#include<stdio.h>

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

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

return 0;
}

It still outputs on the console.

3 Answers

The strange behavior of printf, buffering can be explained with below simple C code. please read through entire thing execute and understand as the below is not obvious (bit tricky)

#include <stdio.h>
int main()
{
   int a=0,b=0,c=0;
   printf ("Enter two numbers");
   while (1)
   {
      sleep (1000);
   }
   scanf("%d%d",&b,&c);
   a=b+c;
   printf("The sum is %d",a);
   return 1;
}

EXPERIMENT #1:

Action: Compile and Run above code

Observations:

The expected output is

Enter two numbers

But this output is not seen

EXPERIMENT #2:

Action: Move Scanf statement above while loop.

#include <stdio.h>
int main()
{
   int a=0,b=0,c=0;
   printf ("Enter two numbers");
   scanf("%d%d",&b,&c);
   while (1)
   {
      sleep (1000);
   }
   a=b+c;
   printf("The sum is %d",a);
   return 1;
}

Observations: Now the output is printed (reason below in the end)(just by scanf position change)

EXPERIMENT #3:

Action: Now add \n to print statement as below

#include <stdio.h>
int main()
{
   int a=0,b=0,c=0;
   printf ("Enter two numbers\n");
   while (1)
   {
      sleep (1000);
   }
   scanf("%d%d",&b,&c);
   a=b+c;
   printf("The sum is %d",a);
   return 1;
}

Observation: The output Enter two numbers is seen (after adding \n)

EXPERIMENT #4:

Action: Now remove \n from the printf line, comment out while loop, scanf line, addition line, printf line for printing result

#include <stdio.h>
int main()
{
   int a=0,b=0,c=0;
   printf ("Enter two numbers");
//   while (1)
//   {
//      sleep (1000);
//   }
//   scanf("%d%d",&b,&c);
//   a=b+c;
//   printf("The sum is %d",a);
   return 1;
}

Observations: The line "Enter two numbers" is printed to screen.

ANSWER:

The reason behind the strange behavior is described in Richard Stevens book.

PRINTF PRINTS TO SCREEN WHEN

The job of printf is to write output to stdout buffer. kernel flushes output buffers when

  1. kernel need to read something in from input buffer. (EXPERIMENT #2)
  2. when it encounters newline (since stdout is by default set to linebuffered)(EXPERIMENT #3)
  3. after program exits (all output buffers are flushed) (EXPERIMENT #4)

By default stdout set to line buffering so printf will not print as the line did not end. if it is no buffered, all lines are output as is. Full buffered then, only when buffer is full it is flushed.

Related