我在C
中有这个小程序main(int argc, char **argv)
{
forkit(4);
}
void forkit(int n)
{
if(n > 0)
{
fork();
printf("%d \n", n);
forkit(n-1);
}
}
打印
4 4 3 3 3 3 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
30个数字,全部用新行。但是,如果我删除\n
语句中的printf
,则会打印出来:
4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1
如果没有新行,它会提供64个数字。
如此小的变化如何产生如此不同的结果?
答案 0 :(得分:5)
非常好的问题,是一些微妙的事情。
正在发生的事情是printf的输出是行缓冲并在换行时刷新。
所有这一切,不会影响大多数程序的输出,只会影响速度。
但是当你分叉时,两个孩子中现在都存在尚未输出的缓冲I / O.使用 in 中的换行符已经发生输出,因此它不再在孩子中待定。
这就是解释。如果不清楚,另一种表达方式是:没有换行符,挂起的输出乘以进程树中未来子节点的数量。使用换行符,它只是过去发生的输出,程序的工作方式与您期望的一样。
请注意,即使没有换行符,输出最终也会被刷新,但是当程序调用{{1}}时会发生这种情况。到那时,它已经分叉并传递了它的挂起(即缓冲 )输出。
顺便说一句,如果你将输出重定向到一个文件,它将是块缓冲,你可能会在两种情况下都看到类似的结果(除了换行符)。