我创建了一个简单的sleepsort算法:
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#define ARR_SIZE 10
void *sleepSort(void *arg) {
usleep(1000 * *(int*) arg);
printf("%d ", *(int*) arg);
return NULL;
}
int main(void) {
srand(time(NULL));
int arr[ARR_SIZE];
for (int i = 0; i < ARR_SIZE; i++)
arr[i] = rand() % 100;
pthread_t thr[ARR_SIZE];
for (int i = 0; i < ARR_SIZE; i++)
pthread_create(thr + i, NULL, sleepSort, (void *)(arr + i));
getchar();
return 0;
}
然而,当我从Linux控制台运行它时,在我输入一个新字符之前,什么都不打印。然而,我修改了我的程序,在每个printf上添加了一个换行符,它就像预期的那样工作了,我不明白为什么。
3条答案
按热度按时间mzsu5hc01#
默认情况下,
stdout
在连接到终端时是行缓冲的。只有在接收到换行符、缓冲区已满、手动刷新句柄或禁用缓冲时,才会向系统写入数据。在此之前,输出只是在缓冲区中累积。所以你需要
stdout
,stdout
的缓冲。默认情况下,
stdout
在连接到终端以外的设备时是完全缓冲的。这也是其他句柄的默认设置,无论它们是否连接到端子。这与行缓冲相同,只是行馈送不会导致刷新。w6lpcovy2#
标准输出是缓冲的,你需要通过以下方式强制缓冲区刷新:
或通过打印LF
如果你想看到输出,你也可以禁用缓冲:
文件:setvbuf
您在godbolt上的程序(
'\n'
将无法工作,因为它不是终端):https://godbolt.org/z/x4xT1M51egcxthw6b3#
然而,当我从Linux控制台运行它时,在我输入一个新字符之前,什么都不打印。然而,我修改了我的程序,在每个printf上添加了一个换行符,它就像预期的那样工作了,我不明白为什么。
printf()
使用缓冲输出来保存系统调用,为了有效地做到这一点,stdio包默认情况下根据输出设备有几种方法来做到这一点。stdout
上,所有的stdio例程都使用一个缓冲区,当标准输出连接到一个非tty设备(文件、管道、套接字等)时,该缓冲区只刷新其内容。stdout
连接到一个物理tty(控制台,或/dev
中的任何tty设备)时,它会切换到一种模式,只有当缓冲区完全填满或在输出上检测到'\n'
字符时,它才刷新缓冲区。这是你观察到的行为。当你输入新的行字符时,输出会显示出来,而不是累积在缓冲区中。另外,当您调用一个输入例程来读取时(这不是通用的,但有些实现会这样做,以允许您打印不以换行符结尾的提示),首先会执行缓冲区刷新。这也仅在输出和输入与终端相关联时发生。setbuff()
指定no buffer的时候,输出是完全没有缓冲的,所以每次printf都会导致一些东西被写入标准输出。如果不想更改默认值(我建议不要将stdout buffer设置为
NULL
,因为这样会严重影响性能),可以不使用换行符强制刷新缓冲区,而只是穿插调用写在你想写的地方
最后,回答你的问题,这样做的主要原因是性能。缓冲输出大大加快了I/O的速度,应该一直使用,除非需要某些特殊特性(如调试程序)。