0

这是我的程序:

#include <stdio.h>
int main(int argc, char* argv[]) {
  char buf[1024] = {0};
  setvbuf(stdout, buf, _IOFBF, 1024);
  printf("error\n");
  printf("%s\n", buf);
}

这是输出:

error
error

Exited: ExitFailure 7

为什么第 3 行和第 4 行都是空行?字符不是'\n'刷新输出缓冲区并在以后被丢弃吗?

4

4 回答 4

3

来电:

printf("error\n");

将 "error\n" 复制到 stdout 的缓冲区,即 now buf,然后将其刷新到屏幕上。

来电:

printf("%s\n", buf);

然后将之前的 printf 调用设置为“error\n”的 buf 再次复制到 buf 并附加另一个 \n,所以 buf 现在是“error\n\n”,这就是你的 2 个空白行的来源。

然后,由于您没有return 0在 main 结束时,最后一次 printf 调用的返回值被解释为 main 的返回值。由于“errno\n\n”是 7 个字符长 printf 将返回 7,并且由于它不是 0,因此运行程序的人将其解释为失败。

于 2010-09-24T17:44:03.943 回答
3

您肯定在调用未定义(或至少未指定)的行为。您声明一个缓冲区,然后通过setvbufto传递它stdout。从那时起,缓冲区您所有,stdout不再归您所有。这意味着您可能无法再访问它。但这正是你所做的。

我无法从标准的措辞中证明这一点,但肯定有一些段落组合可以得出我的结论。

更新: ISO C99 在 7.19.5.6p2 中说关于setvbuf函数:数组的内容在任何时候都是不确定的。所以你看到的只是巧合。您可能还会看到其他任何内容,仅 ISO C99 并不能保证。

更新 2:因为数组的内容是不确定的,所以它们也可能都是非空字符。在这种情况下,buf不再包含字符串。因此,您清楚地调用了未定义的行为

于 2010-09-24T17:46:00.880 回答
1

您的退出代码告诉我 printf 打印了 7 个字符 - 我假设“错误”中有 5 个字符,还有两个“\n”。您的操作系统是否可以添加第 4 行 - 通过打印“退出”的任何内容?

于 2010-09-24T17:40:46.083 回答
1

您的代码的问题在于您将一个缓冲区用于完全不同的任务 - 将其用作中间输出缓冲区并使用其内容将其打印到输出。

你的程序做什么:

  1. 分配一个缓冲区 `buf` 并将 `'\0'` 写入 `buf[0]` 使其成为一个空字符串
  2. 将 I/O 缓冲区设置为 `buf`
  3. 将 "error\n" 写入标准输出 - 这意味着首先写入 `buf`,然后可能会写入屏幕。
  4. `buf` 现在包含字符串“error\n”
  5. 您打印 `buf` 的内容 - 这意味着 `buf` 被复制到自身,这可能会导致稍后出现奇怪的退出失败。这将打印包含错误的第二行。

额外的 \n 字符可能是系统添加的。请注意 \n 不会刷新输出缓冲区,您必须调用刷新函数以确保已发生刷新。

于 2010-09-24T17:47:25.433 回答