【问题标题】:Why does this C program not print anything?为什么这个 C 程序不打印任何东西?
【发布时间】:2019-05-18 14:02:57
【问题描述】:

我有以下代码:

int main()
{
   printf("hello world");
   while(1);
}

应该打印hello world。如果是,为什么?如果不是,为什么? 我在 linux 机器上使用 gcc 来编译代码。

【问题讨论】:

  • 运行时是否打印?
  • 也许吧。也许不吧。取决于缓冲。我的猜测不是。
  • 您可以确定的是字符串将被发送到输出缓冲区。根据我们掌握的信息,它是否出现在输出的任何地方都无法辨别。
  • 注意:while(1);while(1){} 相同。这是你的意图吗?你想要printf之后的循环吗?你想让循环什么都不做吗?

标签: c linux stdout flush


【解决方案1】:

我们不知道。

标准输出缓冲区可以被刷新,但也可以不被刷新。

换句话说,当这个printf("hello world");被执行时,“hello world”将被存储在标准输出缓冲区中。

那么,由于while(1);,我们将陷入无限循环。

此时,我们无法确定标准输出缓冲区是否会被刷新。例如,在这个 Live demo 中,它不会,这是最有可能发生的事情,但一般不能保证。

通常我会添加一个换行符,以确保消息被打印出来。阅读更多Why does printf not flush after the call unless a newline is in the format string?

另一种方法是这样的:

#include <stdio.h>
int main(){
  printf("hello world");
  fflush(stdout);
  while(1);
}

会强制标准输出缓冲区清空自己并将其中存储的任何内容定向到标准输出(通常是您的屏幕)。

正如@hyde 所说,您可以使用原始代码刺激这种行为,例如让gdb 为您刷新缓冲区。在How to unbuffer stdout of legacy running binary without stdbuf and similar tools 阅读更多内容。


这可能是一个假设的场景,但从中吸取的教训是,在调试过程中,许多人使用printf()s,以便查明他们的程序崩溃的位置。

不刷新输出缓冲区可能会导致错误的假设,因为程序员可能认为程序在此printf("here"); 之前崩溃了,但由于上面讨论的原因,情况可能并非如此。

换句话说,“这里”可能没有打印在标准输出(例如屏幕)中,但这并不意味着我们的程序的执行没有达到printf()

【讨论】:

  • 我想知道是否可以轻松生成一个场景,将刷新 stdio 缓冲区?
  • 当然是@hyde,更新了我的答案。 (如果我理解正确的话:))
  • 是的,当然是这样,但我的意思是不更改源代码,也不需要重新编译。我发现了一个相关的问题,其中有一些答案:stackoverflow.com/questions/45460998/…
  • @hyde 好主意,改进了我的答案!并达到 50k 代表!!!!!!!!!! :D 感谢海德的支持!
  • 添加\n 似乎也可以在不使用fflush 的情况下刷新缓冲区。我不确定是否可以依赖这种行为......
【解决方案2】:

在一般情况下,消息不会被打印——至少在大多数类 Unix 平台上是这样。当标准输出是“交互式设备”(“终端”的标准术语)时,默认输出缓冲(通常)是行缓冲。由于您没有打印换行符,因此没有要刷新的行,因此输出保留在程序的缓冲区中。当你中断它时,输出不会被刷新。

仅当您将输出设置为“无缓冲”时,您才会看到输出,或者如果您在进入循环之前执行明确的 fflush(stdout)fflush(0),或者您执行明智的操作并在首先打印的字符串。

setvbuf(stdout, NULL, _IONBF, 0);

(完全缓冲,例如当您将输出传送到另一个程序时,几乎可以保证您也看不到输出。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-12
    • 2015-08-23
    • 2012-12-30
    相关资源
    最近更新 更多