C语言中,printf() 输出数据到标准输出(stdout),但其行为可能会导致困惑,有时需要调用 printf() 后,输出不会立即显示,除非添加了换行符或手动刷新缓冲区。

1、输出缓冲区的行为

标准输出(stdout)通常是行缓冲的,也就是当遇到换行符('\n')时,缓冲区的数据会自动刷新并输出到屏幕。当缓冲区填满或程序正常结束时,也会自动刷新。如果没有触发这些条件,printf() 的输出会暂时保留在缓冲区中,而不会立即显示。

#include <stdio.h>

int main() {
    // 设置 stdout 为无缓冲
    setbuf(stdout, NULL);

    printf("这将会立即打印。\n");

    // 设置 stdout 为行缓冲
    char buffer[BUFSIZ];
    setvbuf(stdout, buffer, _IOLBF, BUFSIZ);

    printf("这将在换行后打印。\n");

    // 强制刷新缓冲区
    fflush(stdout);

    printf("这将在 fflush 后立即打印。\n");

    return 0;
}

2、printf() 需要换行符才能刷新的原因

printf() 会将输出数据放入一个缓冲区。该缓冲区的默认刷新策略是,行缓冲在当遇到换行符('\n')时刷新,全缓冲在当缓冲区满了时刷新,无缓冲在对于 stderr,通常是无缓冲的,即每次输出都会立即显示。在大多数系统中,标准输出(stdout)是行缓冲的,所以一般会发现,没有换行符,输出会滞留在缓冲区中。有换行符会立即刷新并显示。

#include <stdio.h>
#include <unistd.h> // for sleep()
 
int main() {
    printf("This is the first line");
    sleep(3); // simulate some delay 
    printf("This is the second line\n");
    return 0;
}

3、解决方法

标准输出(stdout) 是行缓冲的,因此输出会在遇到换行符或缓冲区满时刷新。没有换行符时,你可以使用 fflush(stdout) 或禁用缓冲区来确保输出立即显示。stderr 是无缓冲的,适合需要立即输出的场景。

1)添加换行符

#include <stdio.h>

int main() {
    printf("Hello\n");  // 使用换行符强制刷新缓冲区
    return 0;
}

2)使用 fflush() 手动刷新缓冲区

#include <stdio.h>

int main() {
    printf("Hello");  // 没有换行符
    fflush(stdout);   // 手动刷新缓冲区

    return 0;
}

3)禁用缓冲

如要 stdout 每次输出时都立即显示,可以禁用缓冲。setbuf(stdout, NULL) 禁用了标准输出的缓冲,使所有输出立即生效。

#include <stdio.h>

int main() {
    setbuf(stdout, NULL);  // 禁用缓冲区
    printf("Hello");  // 输出会立即显示

    return 0;
}

4)使用 stderr

stderr(标准错误)是无缓冲的,所以它的输出不会被缓冲。可以使用它来立即显示内容。

#include <stdio.h>

int main() {
    fprintf(stderr, "Hello");  // 无缓冲,立即显示
    return 0;
}

推荐文档