cfflush

what is the different of using fflush(stdout) and not using it


#include <stdio.h>

int main()
{
   printf("Hello");
   fflush(stdout);
   return 0;
}
#include <stdio.h>

int main()
{
   printf("Hello");
   return 0;
}

I'm trying to understand the use of fflush(stdout) and what is the difference between the 2 programs above?


Solution

  • In a normal C program running on a modern OS, file access is buffered twice (or more when you count buffers like the buffer in your drive). One buffer is implemented in the FILE structure and the other is implemented in the kernel.

    Often, the FILE structure buffers the content in a buffer inside of your program. When you write something to a buffered file, the content is keep in the buffer, inside of the running program. It is written to the OS when the buffer is full and, when the buffering mode is line buffered, at the end of a line. This data is written to the OS by a syscall, for example write(). The buffer is there because a syscall requires a context switch from the user program to the kernel, this is relatively expensive (slow), the buffer is here to reduce the number of syscalls. You could also use the syscalls from your program directly without the stdio functions, however, this functions are less portable and more complex to handle. A fflush(stdout) checks if there are any data in the buffer that should be written and if so, the underlying syscall is used to write the data to the OS.

    When the syscall returns, the data is in your kernel. But modern operating systems buffer this data as well. This is used to reduce the number of disk writes, reduce latency and other things. This buffer is completely independent of the FILE buffer inside your program.

    Note that this does not apply to all systems. For example microcontroller environments may provide some stdio.h functions that write directly to a UART, without any buffer, neither inside FILE nor any (probably non-existent) OS.

    To see what fflush() does to a running program, compare this programs:

    int main(void)
    {
      fputs("s",stdout);
      fputs("e",stderr);
    }
    

    and

    int main(void)
    {
      fputs("s",stdout);
      fflush(stdout);
      fputs("e",stderr);
    }
    

    On Linux, stderr is not buffered by default, so fputs("e",stderr); will print the data immediately. On the other hand, fputs("s",stdout); is line buffered by default on Linux so the data is not printed immediately. This causes the first program to output es and not se, but the second one outputs se.

    You can change the buffer modes with setvbuf()