下面的这段代码所要我们求的是总共打印出多少个“-”。
include <stdio.h>
#include <unistd.h>
int main(int argc,char*argv[])
{
int i;
for(i =0; i<2 ;i++)
{
fork();
//printf("-");
printf("-\n");
}
return 0;
}
题目给出了两种打印方法,一种加了“\n”,另一种未加,也就是代码段的8、9两行的打印语句。
加了“\n”的很好理解总共打印出6个“-”,下面的图解释了原理:
在执行了fork()之后,产生了一个子进程,之后执行printf(“-\n”)语句,所以将会打印6个“-”。
但是在我们将代码中的第9行注释掉,使用第8行的代码,那么又会打印几次呢?这两个语句就差了一个“\n”,恰恰就是这个“\n”使执行结果发生了变化。因为在执行打印语句printf()时,它并不是立即将内容打印出来,而是放到了一个缓冲区中,在缓冲区满之后才会将缓冲区中的内容打印出来。而我们在所打印的内容之后加上“\n”之后就意味着告诉printf()函数马上将缓冲区中的内容打印出来。
所以在没加上“\n”的时候,每次执行printf的时候就会向缓冲区中加入一个“-”,每个进程都有一个属于自己的缓冲区,在fork()的时候,子进程将会拷贝父进程的缓冲区。所以执行过程如下图所示:
在i=0时,fork一次,此时产生了A、C两个进程。A的缓冲区为:-,C的缓冲区为-
在i=1时,对A、C两个进程分别fork了一次,二者的子进程分别为B和D。
进程A会再次执行printf语句,因此A的缓冲区为:- -,C进程同理,因此C的缓冲区也为:- -
而B进程创建出来时,A的缓冲区已经有了一个-,因此B进程会复制A进程的缓冲区,并且还会调用一次printf,因此B的缓冲区为:- -。D进程同理也为:- -。
因此这种情况下会打印8个-
即为:
i=0,A
i=1,A
i=0,C
i=1,C
i=1,B(会复制i=0,A,因此有两个-)
i=1,D(会复制i=0,C,因此也有两个-)