【问题标题】:why doesn't this c programme print the first printf statement?为什么这个 c 程序不打印第一个 printf 语句?
【发布时间】:2011-11-09 06:06:35
【问题描述】:
#include<stdio.h>
#include <unistd.h>
int main(){
      while(1)
      {

              fprintf(stdout,"hello-out");
              fprintf(stderr,"hello-err");
              sleep(1);
      }
      return 0;
}

在 gcc 中编译这个程序并执行它只打印 hello-err 而不是 hello-out。为什么会这样?有人可以解释它背后的原因吗?

【问题讨论】:

  • 您在哪里查看打印的文本?第一个printf 打印到stdout,第二个打印到stderr。在您的情况下,可能是不同的输出流
  • @JimBuck-我正在开发 Fedora linux。
  • @Nekto-我认为 stdout 和 stderr 输出都定向到终端。因为我能够在终端中看到 hello-err。

标签: c printf


【解决方案1】:

如果您在消息中添加'\n',它将(或应该),即。 "hello-out\n".

原因是stdout缓冲 以提高效率,而stderr 不缓冲它的输出,更适合错误消息和需要处理的事情立即打印。

stdout通常会在以下情况刷新

  • 要打印换行符 (\n)
  • 你从stdin读到
  • fflush() 被调用

编辑:在我的计算机崩溃之前我想添加的另一件事......两次......您还可以使用setbuf(stdout, NULL); 来禁用stdout 的缓冲。在我不得不使用 write() (Unix) 并且不希望我的输出被缓冲时,我已经这样做了。

【讨论】:

  • @bornfree:别担心,希望我解释清楚。
【解决方案2】:

它不会总是将输出打印到 stdout,因为根据设计,stdout 是 BUFFERED 输出,而 stderr 是无缓冲的。通常,对于缓冲的输出流,在系统“空闲”之前不会转储流。因此,数据可以在刷新之前继续缓冲很长时间。如果你想强制缓冲区刷新,你可以手动使用fflush

#include<stdio.h>
#include <unistd.h>
int main(){
      while(1)
      {

              fprintf(stdout,"hello-out");
              fflush(stdout); /* force flush */
              fprintf(stderr,"hello-err");
              sleep(1);
      }
      return 0;
}

更新:stdout 在连接到终端时是行缓冲的,否则只是缓冲(例如重定向或管道)

【讨论】:

    【解决方案3】:

    您忘记了字符串中的换行符(注明\n)。或者你需要在sleep(1);之前调用fflush(NULL);或至少fflush(stdout);

    fprintf(stdout, ...)printf(...) 相同

    您需要输出换行符或调用fflush,因为(至少在Linux 上)stdout FILE 缓冲区是行缓冲的。这意味着 C 库正在缓冲数据,并且当缓冲区足够满时,或者当您使用新行刷新它时,或者通过调用 fflush .需要缓冲是因为系统调用成本很高(为要输出的每个字节调用write 真的太慢了​​)。另请阅读setbuf 的手册页

    【讨论】:

    • 您能否详细说明为什么需要这样做?我想了解其背后的原因。
    • AusCBloke 的回答解释了这一点。
    • 正如其他人所回答的那样,因为它被缓冲以减少 I/O 操作。调用 fflush() 将强制刷新缓冲区。