【问题标题】:Why does printf() not print anything before sleep()?为什么 printf() 在 sleep() 之前不打印任何内容?
【发布时间】:2008-12-03 18:42:34
【问题描述】:

我只是根据 Kernighan 和 Ritchie 的书学习 C;我在第四章的基础知识(“功能和程序结构”)。前几天我对sleep()函数产生了好奇,所以尝试这样使用它:

#include <stdio.h>
#include <unistd.h>

int main(void)
{
  printf(" I like cows.");
  sleep(5);
  return 0;
}

问题是程序的输出,看起来它先是sleep(),然后是printf(),换句话说,它等待五秒钟然后打印字符串。所以我想,也许程序到达sleep() 的速度太快了,以至于它不会让printf() 像我想要的那样完成他的工作,那就是打印字符串然后休眠。

如何显示字符串然后让程序进入睡眠状态? 编译器是 OpenBSD 4.3 中的 GCC 3.3.5 (propolice)。

【问题讨论】:

    标签: c stdout buffering


    【解决方案1】:

    printf() 写入通常是行缓冲的stdout(默认输出流)。在调用sleep 时,缓冲区没有被刷新,所以没有显示任何内容,当程序退出时,所有流都会自动刷新,这就是它在退出之前打印的原因。打印换行符通常会导致流被刷新,或者您可以使用fflush 函数:

    int main(void)
    {
      printf(" I like cows.\n");
      sleep(5);
      return 0;
    }
    

    或:

    int main(void)
    {
      printf(" I like cows.");
      fflush(stdout);
      sleep(5);
      return 0;
    }
    

    如果您要打印到没有行缓冲的流,如果stdout 被重定向或您正在写入文件,那么简单地打印换行符可能不起作用。在这种情况下,如果您想立即写入数据,您应该使用fflush

    【讨论】:

    • 在字符串中添加 \n 的原因是 printf 到控制台是行缓冲的。但是,如果将其重定向到文件,则可能还不够,因为它使用了不同的缓冲方案。
    • 那么有趣的问题是,如何判断当前文件指针使用的是哪种缓冲模式?
    • @Paul,对,这就是为什么我说它通常会导致流被刷新,但我会继续澄清。
    • @Vinko,没有标准函数可以告诉您流的缓冲模式是什么,但许多实现都有自己的函数(例如 glibc 有 __flbf 和 __fbufsize)。
    • @RobertGamble,好吧,我知道fflush (stdout) 是未定义行为。
    【解决方案2】:

    您的问题是 printf (以及使用 stdio 库写入标准输出(标准输出)的任何其他内容)被缓冲 - 如果它进入控制台,则缓冲行,如果进入文件,则缓冲大小。如果您在printf 之后执行fflush(stdout);,它将执行您想要的操作。您可以尝试在字符串中添加一个换行符 ('\n'),只要您不将标准输出重定向到文件,这将是正确的。

    我不能 100% 确定,但我认为 stderr 没有缓冲,这可能会导致混淆,因为您可能会在之前对 stdout 进行的输出之前看到对 stderr 的输出。

    【讨论】:

    • printf 没有缓冲,它正在写入的流是。
    • stderr 通常是无缓冲的(尽管它可能是行缓冲的)。
    • 为什么换行符('\n') 起作用?
    • @johngonidelis 因为正如我之前所说,它是行缓冲的。当它看到一行的结尾时,它会刷新缓冲区。
    【解决方案3】:

    缓冲意味着所有的输出都存储在一个地方(称为缓冲区),并在其中存在一定数量的数据后输出。这样做是出于效率原因。

    一些(大多数?)实现在写入控制台时会在换行符后清除缓冲区,因此您也可以尝试

    printf(" I like cows.\n");
    

    而不是调用 fflush()

    【讨论】:

      【解决方案4】:

      我实现了时间遭遇如下;

      for (int i = 1; i <= 60; i++) {
          printf("%02d", i);
          fflush(stdout);
          sleep(1);
          printf("\b\b");
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-26
        • 2022-01-09
        • 1970-01-01
        相关资源
        最近更新 更多