Question

Why `printf` Flushes on Newlines in C: Buffering Explained

cprintfflush

Question

In C, why does printf() sometimes not display output immediately unless the format string contains a newline character like \n? Is this behavior required by POSIX, and how can I make printf() flush output immediately after every call?

Example:

#include <stdio.h>

int main(void) {
    printf("Hello");
    /* output may not appear yet */

    printf(" world\n");
    /* now the buffered output appears */

    return 0;
}

Short Answer

By the end of this page, you will understand how C output buffering works, why printf() often waits before showing text, why a newline can trigger flushing on terminals, and how to force output to appear immediately using functions such as fflush() or by changing buffering mode.

Concept

printf() writes to a stream, usually stdout, not directly to the screen one character at a time. That stream is typically buffered.

A buffer is temporary memory where output is collected before it is actually written to the terminal, file, or pipe. Buffering improves performance because writing many small pieces one by one is expensive compared with writing larger chunks at once.

The main buffering modes

C standard I/O commonly uses three buffering behaviors:

  • Unbuffered: output is written immediately.
  • Line buffered: output is written when a newline is encountered, when the buffer fills, or when the stream is flushed.
  • Fully buffered: output is written only when the buffer fills or when you explicitly flush it.

Why newline often matters

When stdout is connected to an interactive terminal, it is commonly line buffered. That means:

  • printf("Hello") may stay in memory for a while.
  • printf("Hello\n") often causes the whole line to be flushed.

This is why adding \n often makes text appear immediately.

Is it POSIX behavior?

The exact buffering strategy is implementation-defined, but POSIX and common C library behavior make this pattern normal:

  • stdout connected to a terminal is typically line buffered.
  • stdout redirected to a file or pipe is often fully buffered.
  • stderr is typically unbuffered.

So this behavior is not really about printf() itself. It is about the buffering mode of the stream it writes to.

Why this matters in real programs

If your program prints prompts, progress updates, logs, or status messages, buffering affects when users actually see them. A program may be correct but still appear to "hang" if output has not been flushed yet.

Mental Model

Think of stdout like a mail tray on your desk:

  • printf() puts letters into the tray.
  • The operating system does not necessarily deliver each letter immediately.
  • A newline is often like saying, "This message is complete; send it now."
  • fflush(stdout) is you manually taking the tray to the mailbox.

So printf() does not always mean "show this now." It often means "add this to the outgoing buffer."

Take Quiz

Syntax and Examples

Basic syntax

printf("message");
fflush(stdout);

printf() writes formatted text to stdout. fflush(stdout) forces buffered output for stdout to be written immediately.

Example: output may be delayed

#include <stdio.h>
#include <unistd.h>

int main(void) {
    printf("Working...");
    sleep(2);
    printf(" done\n");
    return 0;
}

If stdout is line buffered, Working... may not appear before the sleep(2) finishes because there is no newline yet.

Example: force immediate output

#include <stdio.h>
#include <unistd.h>

int main(void) {
    printf("Working...");
    fflush(stdout);
    sleep(2);
    printf(" done\n");
    return 0;
}

Now Working... is flushed before the pause, so the user sees it immediately.

Example: change buffering mode

#include <stdio.h>
#include <unistd.h>

int main(void) {
    setvbuf(stdout, NULL, _IONBF, 0);

    printf("A");
    sleep(1);
    printf("B");
    sleep(1);
    printf("C\n");

    return 0;
}

setvbuf() with _IONBF makes stdout unbuffered, so each printf() is written right away.

Important note

Changing buffering with setvbuf() should be done before performing normal I/O on that stream.

Step by Step Execution

Consider this program:

#include <stdio.h>
#include <unistd.h>

int main(void) {
    printf("Hi");
    sleep(1);
    printf(" there\n");
    return 0;
}

Step by step:

  1. printf("Hi") writes Hi into the stdout buffer.
  2. Because there is no newline, the library may keep that text in memory.
  3. sleep(1) pauses the program for one second.
  4. During that pause, the user may still see nothing.
  5. printf(" there\n") adds more text, including a newline.
  6. Since stdout is often line buffered on terminals, the newline triggers a flush.
  7. The terminal now receives Hi there\n and displays it.
  8. When the program exits normally, remaining buffered output is also flushed.

Now compare with this version:

#include <stdio.h>
#include <unistd.h>

int main(void) {
    printf("Hi");
    fflush(stdout);
    sleep(1);
    printf(" there\n");
    return 0;
}

This time:

  1. printf("Hi") writes into the buffer.
  2. fflush(stdout) forces that buffered text to be written immediately.
  3. The user sees Hi before the pause.
  4. After one second, printf(" there\n") prints the rest.

Real World Use Cases

Interactive command-line programs

Programs that print prompts often need immediate output:

printf("Enter your name: ");
fflush(stdout);
scanf("%99s", name);

Without flushing, the prompt might not appear before input is requested.

Progress indicators

Command-line tools often print progress updates without a newline:

printf("Loading... %d%%\r", percent);
fflush(stdout);

This lets the same line update visibly.

Logging to files or pipes

When output is redirected, stdout may become fully buffered. That means logs may appear in larger chunks instead of instantly.

Long-running scripts and services

Status output during long tasks may need explicit flushing so users or monitoring tools can see current progress.

Take Quiz

Real Codebase Usage

In real projects, developers usually handle buffering in a few common ways.

1. Flush after prompts or partial lines

A common pattern is:

printf("Choice: ");
fflush(stdout);

This is especially important before reading input.

2. Use stderr for immediate diagnostic messages

Errors and warnings are often sent to stderr because it is typically unbuffered or less delayed:

fprintf(stderr, "Error: failed to connect\n");

3. Explicit progress updates

For progress bars, spinners, or same-line status messages, developers often combine \r with fflush(stdout).

4. Configure buffering once at startup

Some command-line tools set buffering mode early:

setvbuf(stdout, NULL, _IOLBF, 0);

or

setvbuf(stdout, NULL, _IONBF, 0);

This avoids repeated fflush() calls in simple tools.

5. Be careful with performance

Flushing after every small write can slow a program down. In real codebases, developers usually flush only when immediate visibility matters.

Common Mistakes

Mistake 1: Assuming printf() always prints immediately

Broken expectation:

printf("Processing...");
sleep(5);

You might expect Processing... to appear first, but it may stay buffered.

Fix:

printf("Processing...");
fflush(stdout);
sleep(5);

Mistake 2: Believing newline always flushes everywhere

A newline often flushes stdout when connected to a terminal, but not necessarily when output is redirected to a file or pipe.

printf("message\n");

This may still be buffered differently depending on where stdout goes.

Mistake 3: Using fflush() on input streams for this purpose

This is wrong for output control:

fflush(stdin); /* not for portable input handling */

Use fflush(stdout) to flush output.

Mistake 4: Calling setvbuf() too late

Broken pattern:

printf("Hello");
setvbuf(stdout, NULL, _IONBF, 0);

Buffering mode should generally be set before normal stream I/O begins.

Mistake 5: Flushing after every output without need

This works but may hurt performance:

printf("x");
fflush(stdout);
printf("y");
fflush(stdout);

Only flush when timely display matters.

Comparisons

ConceptWhat it doesTypical behaviorBest use
printf() onlyWrites to stdout bufferMay not appear immediatelyNormal formatted output
printf(...\n)Writes a line ending with newlineOften flushes on terminalsUser-facing line output
fflush(stdout)Forces buffered output to be writtenImmediate flushPrompts, progress, partial lines
fprintf(stderr, ...)Writes to error streamTypically less bufferedErrors and diagnostics
setvbuf(stdout, NULL, _IONBF, 0)Disables bufferingEvery write is immediateDebugging, interactive tools

stdout vs stderr

StreamCommon bufferingTypical use
stdoutLine buffered on terminal, fully buffered otherwiseNormal program output
stderrOften unbufferedErrors, warnings

fflush() vs newline

ApproachReliable for immediate output?Notes
Add \nSometimesCommonly works on terminals
fflush(stdout)YesBest explicit choice
Unbuffered mode with setvbuf()YesUseful, but can reduce performance
Take Quiz

Cheat Sheet

Quick reference

printf("Hello");           /* may stay buffered */
printf("Hello\n");         /* often flushes on terminal */
fflush(stdout);            /* force flush now */
fprintf(stderr, "Oops\n"); /* error output, often immediate */
setvbuf(stdout, NULL, _IONBF, 0); /* disable buffering */

Rules to remember

  • printf() writes to stdout, which is usually buffered.
  • Newline often causes a flush only when stdout is line buffered.
  • Terminal output is commonly line buffered.
  • File and pipe output is often fully buffered.
  • stderr is commonly unbuffered.
  • Use fflush(stdout) when output must appear immediately.
  • Call setvbuf() before regular I/O on the stream.

Good pattern for prompts

printf("Enter value: ");
fflush(stdout);

Good pattern for progress updates

printf("%d%%\r", progress);
fflush(stdout);

Edge case

A program that crashes before normal exit may lose buffered stdout output if it was never flushed.

FAQ

Why does printf() not print immediately in C?

Because stdout is usually buffered. printf() often writes to a memory buffer first, not directly to the terminal.

Does a newline always flush printf() output?

No. It often does when stdout is connected to a terminal and line buffered, but not in every environment.

Is this behavior defined by POSIX?

POSIX-compatible systems commonly use line buffering for terminal stdout, but the exact buffering behavior depends on the C library and stream setup.

How do I force printf() to flush immediately?

Call fflush(stdout) after printf().

Should I use stderr instead of stdout for immediate output?

Use stderr for errors and diagnostics. For normal output, prefer stdout and flush it explicitly when needed.

Can I disable buffering completely?

Yes. You can call setvbuf(stdout, NULL, _IONBF, 0); early in the program.

Why does my prompt not appear before scanf()?

Because the prompt may still be buffered. Flush stdout after printing the prompt.

Take Quiz

Mini Project

Description

Build a small interactive terminal program that asks the user for a name and then shows a fake loading progress message. This demonstrates why flushing matters for prompts and progress output that do not end with a newline.

Goal

Create a C program where prompts and progress updates appear immediately, even without relying on newline-triggered flushing.

Requirements

  • Print a prompt asking for the user's name without ending the prompt with a newline.
  • Make sure the prompt is visible before reading input.
  • Display a progress message that updates several times on the same line.
  • Force each progress update to appear immediately.
  • Print a final greeting after the progress completes.
Take Quiz

Keep learning

Related questions

View more