这个简单的程序如何工作,I / O相关

时间:2010-09-24 17:28:47

标签: c newline buffer outputstream

这是我的计划:

#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 个答案:

答案 0 :(得分:3)

电话:

printf("error\n");

将“error \ n”复制到stdout的缓冲区(现为buf),然后将其刷新到屏幕。

电话:

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

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

然后,由于在main的末尾没有return 0,最后一次printf调用的返回值被解释为main的返回值。由于“errno \ n \ n”是7个字符,因此printf将返回7,并且因为它不是0,所以无论谁运行该程序都会将其解释为失败。

答案 1 :(得分:3)

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

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

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

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

答案 2 :(得分:1)

你的退出代码告诉我printf打印了7个字符 - 我假设“错误”为5,另外两个“\ n”。你的操作系统可以添加第4行 - 通过任何打印“退出”吗?

答案 3 :(得分:1)

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

你的计划做了什么:

  1. 分配缓冲区`buf`并将''\ 0'`写入`buf [0]`使其成为空字符串
  2. 将I / O缓冲区设置为`buf`
  3. 将“error \ n”写入标准输出 - 这意味着首先是“buf”然后可能是屏幕。
  4. `buf`现在包含字符串“error \ n”
  5. 你打印`buf`的内容 - 这意味着`buf`被复制到自身,这可能会导致以后奇怪的退出失败。这将打印包含错误的第二行。
  6. 额外\ n字符可能由系统添加。请注意\ n不会刷新输出缓冲区,您必须调用刷新函数以确保已发生刷新。