You write a perfectly valid printf statement, run your program, and nothing appears. Then you add n at the end and it works. Here is exactly why that happens and how to control it.
The Problem
Run this and watch what happens:
#include <stdio.h>
#include <unistd.h>
int main() {
printf("Loading...");
sleep(3);
printf(" donen");
return 0;
}
You expect to see Loading… immediately, then done three seconds later. What you actually see: nothing for three seconds, then both strings appear together.
This is stdout buffering.
How stdout Buffering Works
C does not write output to the terminal character by character. Writing to a terminal is slow — it involves a system call, which means switching from user space to kernel space. To avoid this overhead, the C runtime batches your output in a memory buffer and flushes it in one go.
There are three buffering modes:
- Unbuffered — output goes directly to the terminal, one character at a time.
stderris unbuffered by default. - Line-buffered — output is held until a newline character (
n) is written, then the whole buffer flushes. This is the default forstdoutwhen it is connected to a terminal. - Fully buffered — output is held until the buffer is full (typically 4KB or 8KB). This is the default for
stdoutwhen it is redirected to a file or pipe.
This is why n fixes it when you are running in a terminal — it triggers a flush in line-buffered mode.
The Three Ways to Fix It
1. Add n to the printf format string
printf("Loading...n");
Simple. Works when you are printing a complete line. Does not work when you want output mid-line (like a progress indicator).
2. Use fflush(stdout)
#include <stdio.h>
#include <unistd.h>
int main() {
printf("Loading...");
fflush(stdout); /* flush the buffer immediately */
sleep(3);
printf(" donen");
return 0;
}
fflush(stdout) forces everything currently in the stdout buffer to be written to the terminal right now, regardless of whether there is a newline. Use this when you need output to appear before a newline would naturally occur.
3. Disable buffering entirely with setbuf
#include <stdio.h>
int main() {
setbuf(stdout, NULL); /* NULL disables buffering */
printf("This prints immediately");
printf(" and so does this");
return 0;
}
This sets stdout to unbuffered mode for the entire program. Useful during debugging. Not recommended for production — you lose the performance benefit of buffering.
Why stderr Always Shows Immediately
#include <stdio.h>
int main() {
printf("This might be buffered");
fprintf(stderr, "This always appears immediatelyn");
return 0;
}
stderr is unbuffered by default. That is why error messages appear even when your program crashes before flushing stdout. If you are printing diagnostic output and it is not appearing, write to stderr instead.
The Redirect Problem
Buffering behaviour changes when you redirect output:
./myprogram > output.txt
Now stdout is connected to a file, not a terminal. C switches from line-buffered to fully-buffered mode automatically. If you are also dealing with input buffering issues, see our guide on how scanf works and why it fails silently. Your n no longer triggers a flush. The buffer only flushes when it fills up (usually 8KB) or when the program exits normally.
This is a common source of confusion when debugging programs with piped or redirected output. The fix is the same: call fflush(stdout) at the point where you need output to appear.
What Happens on Normal Program Exit
When your program calls return 0 from main or calls exit(), the C runtime flushes and closes all open streams. This is why you usually see all your output even without explicit flushes — it all arrives at program termination.
The exceptions: programs that crash (segfault, abort), programs killed with SIGKILL, or programs that call _exit() instead of exit(). In these cases the buffer never flushes and output is lost.
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("You will never see this");
_exit(0); /* skips fflush — buffer is lost */
}
TL;DR
- stdout is line-buffered when connected to a terminal —
ntriggers a flush - stdout is fully-buffered when redirected to a file or pipe —
ndoes nothing - stderr is always unbuffered
- Call
fflush(stdout)when you need output to appear without a newline - Call
setbuf(stdout, NULL)to disable buffering for the whole program