linux C语言中有关'\n'的疑惑!


进程的创建:
 题目:编写一个程序,输入两个整数并求和输出,然后创建一个子进程,当进程调度程序调度到父进程或子进程时特输出不同的信息。(父进程输出:I am  father process! My Id=进程号; 子进程输出:I am  son process ! my  id=***)
代码如下:
(1)
//test1.c
#include<stdio.h>
int  main()
{
   int m = 5 , n = 15;
   int pid_t;
    printf("The Sum of m and n is:%d\n",m + n);  pid_t = fork();
 if(pid_t == 0)
{
printf("I am son process ! My process id = %d\n",getpid());
}
else
{
      printf("I am father process ! My id = %d\n",getpid());
}
  return 0;
}
编译程序test1.c并运行后得到运行结果:
[u2342010345@localhost u2342010345]$ gcc -o test1 test1.c
[u2342010345@localhost u2342010345]$ ./test1
The Sum of m and n is:20
I am son process ! My process id = 4223
I am father process ! My id = 4222

我的问题是,为什么我将红体字部分改为 printf("The Sum of m and n is:%d",m + n);
即将printf函数当中的'\n'去掉之后为什么改语句执行了两次?
即运行结果为:
[u2342010345@localhost u2342010345]$ gcc -o test1 test1.c
[u2342010345@localhost u2342010345]$ ./test1
The Sum of m and n is:20I am son process ! My process id = 4554
The Sum of m and n is:20I am father process ! My id = 4553

确实不是很明白为什么会出现这样奇怪的结果,按道理
用fork函数创建子进程时,之前的语句不会再子进程中存在的。

15 个解决方案

#1


printf并没有执行两次,问题在于它的缓冲机制。
printf的内容先输出到缓冲区,程序继续执行,然后系统选择一个合适的时机把缓冲区里的内容打印到屏幕,这样可以提高程序执行的效率。
fork的时候子进程要从父进程复制很多数据,缓冲区内容也在其中。
所以,区别就在于,fork的时候缓冲区的内容是否已经到了屏幕。如果还没有,那么缓冲区里的内容就会从父进程和子进程各自打印一次到屏幕。
\n的作用就是清空缓冲区把所有内容打印到屏幕上。

#2


如果去掉\n
printf("The Sum of m and n is:%d",m + n); 
fflush(stdout); // 强制清空缓冲区
pid_t = fork();
这样也只输出一次

#3


printf的缓冲有时候还会带来其他问题。比如:
void f() {}
int main()
{
    printf("AAA\n");
    f();
    printf("BBB");
    *(int*)0 = 0;
}
我运行的结果只有AAA, 没有BBB。这是因为它还没来得及从缓冲区输出,程序就挂了。
如果调程序的时候遇到这种情况,就很可能是错误的怀疑是死在了函数f()里面。

#4


没有加\n的时候 The Sum of m and n is:20在缓冲里面没输出,
fork的时候子进程拷贝了父进程的数据,所以父子进程的缓冲里面
都有The Sum of m and n is:20,在各自打印的时候就变成你的样子了

#5


引用 1 楼 brookmill 的回复:
\n的作用就是清空缓冲区把所有内容打印到屏幕上

哦,第一次听说。请教一下,是系统事实如此还是有文档正式说过的呢?

#6


参见APUE 172页

#7


学习了。嘎嘎。

#8


引用 1 楼 brookmill 的回复:
printf并没有执行两次,问题在于它的缓冲机制。
printf的内容先输出到缓冲区,程序继续执行,然后系统选择一个合适的时机把缓冲区里的内容打印到屏幕,这样可以提高程序执行的效率。
fork的时候子进程要从父进程复制很多数据,缓冲区内容也在其中。
所以,区别就在于,fork的时候缓冲区的内容是否已经到了屏幕。如果还没有,那么缓冲区里的内容就会从父进程和子进程各自打印一次到屏幕。
\n的作……
介绍得比较专业!

#9


fork后子进程会保留父进程的缓冲区;
标准输出默认是行缓冲,有两种情况会冲洗缓冲区并把数据输出到设备:1,当缓冲区满时,2,当遇到'\n'字符时。
可以用下面的代码试一下


int main(void)
{
   printf("Hello World!");
   while(1);
   return 0;
}


#include <stdio.h>

int main(void)
{
  printf("Hello\n");
  printf("World");
  while(1);
  return 0;
}

但当打印的字符串足够长时(充满缓冲区),字符串还是会被打印出来的。

#10


该回复于2010-10-14 14:01:26被版主删除

#11


呵呵,这是个经典的Linux问题

#12


引用 1 楼 brookmill 的回复:
printf并没有执行两次,问题在于它的缓冲机制。
printf的内容先输出到缓冲区,程序继续执行,然后系统选择一个合适的时机把缓冲区里的内容打印到屏幕,这样可以提高程序执行的效率。
fork的时候子进程要从父进程复制很多数据,缓冲区内容也在其中。
所以,区别就在于,fork的时候缓冲区的内容是否已经到了屏幕。如果还没有,那么缓冲区里的内容就会从父进程和子进程各自打印一次到屏幕。
\n的……

我以前也遇到过同样的问题,\n 刷新缓冲区并输出

#13


学习了

#14


\n并不会在所有的情况下都清除缓冲区
参考setvbuf函数就知道了
缓冲有三种,区域缓冲,无缓冲和行缓冲
\n只有在行缓冲这种情况下才会把所有的信息都显示出去
当然,在无缓冲的情况下没有\n也不需要刷新缓冲区就会把刚刚的显示出来

#15


引用 6 楼 xryang 的回复:
参见APUE 172页

学习了,谢谢!
智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告