这个简单的程序如何工作,与 I/O 相关
这是我的程序:
#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'
不是会刷新输出缓冲区并稍后被丢弃吗?
This is my program:
#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);
}
And this is the output:
error
error
Exited: ExitFailure 7
Why are both lines 3 and line 4 blank lines ? Isn't the character '\n'
flushing the output buffer and being discarded later?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您肯定会调用未定义(或至少未指定)的行为。您声明一个缓冲区,然后通过
setvbuf
将其传递到stdout
。从那时起,缓冲区就由stdout
拥有,而不是由您拥有。这意味着您可能无法再访问它。但这正是你所做的。我无法从标准的措辞中证明这一点,但肯定有一些段落的组合得出了我的结论。
更新: ISO C99 在 7.19.5.6p2 中关于
setvbuf
函数的说明:数组的内容在任何时候都是不确定的。所以你怎么做?所看到的只是巧合。您可能还会看到其他内容,仅靠 ISO C99 并不能保证。更新2:因为数组的内容是不确定的,所以它们也可能都是非空字符。在这种情况下,
buf
不再包含字符串。因此,您显然会调用未定义的行为。You are certainly invoking undefined (or at least unspecified) behavior. You declare a buffer and then pass it via
setvbuf
tostdout
. From that point on, the buffer is owned bystdout
and not you anymore. That means you may not access it anymore. But this is exactly what you do.I cannot prove it from the wording of the standard, but there sure is some combination of paragraphs that leads to my conclusion.
Update: ISO C99 says in 7.19.5.6p2 about the
setvbuf
function: The contents of the array at any time are indeterminate. So what you are seeing is just coincidence. You might also see anything else, there is no guarantee from ISO C99 alone.Update 2: Because the contents of the array are indeterminate, they might as well all be non-null characters. And in that case,
buf
does not contain a string anymore. Therefore, you clearly invoke undefined behavior.调用:
将“error\n”复制到 stdout 的缓冲区(现在是
buf
),然后将其刷新到屏幕。调用:
然后将 buf(之前的 printf 调用已设置为“error\n”)再次复制到 buf 并附加另一个 \n 到其中,因此 buf 现在是“error\n\n”,这就是您的 2 个空行的位置来自。
然后,由于您在 main 末尾没有
return 0
,所以最后一个 printf 调用的返回值被解释为 main 的返回值。由于“errno\n\n”的长度为 7 个字符,因此 printf 将返回 7,并且由于它不是 0,因此运行该程序的任何人都会将其解释为失败。The call:
copies "error\n" into stdout's buffer, which is now
buf
, and then flushes that to the screen.The call:
Then copies buf, which the previous printf call had set to "error\n" to buf again and appends another \n to it, so buf is now "error\n\n", so that's where your 2 blank lines come from.
Then since you did not
return 0
at the end of main the return value from the last printf call was interpreted as the return value of main. Since "errno\n\n" is 7 characters long printf would have returned 7, and since that is not 0 it was interpreted as a failure by whoever ran the program.你的退出代码告诉我 printf 打印了 7 个字符 - 我假设“错误”中有 5 个字符,还有两个“\n”。第 4 行是否可以由您的操作系统添加 - 通过任何打印“Exited”的内容?
Your exit code tells me that printf printed 7 characters - I assume 5 in "error" and two more "\n"s. Could line 4 be added by your OS - by whatever prints "Exited"?
您的代码的问题在于您使用一个缓冲区来执行完全不同的任务 - 将其用作中间输出缓冲区并使用其内容将其打印到输出。
您的程序的作用:
多余的\n字符可能是系统添加的。请注意, \n 不会刷新输出缓冲区,您必须调用刷新函数以确保已发生刷新。
The problem with your code is that you use one buffer for completely distinct tasks - using it as an intermediate output buffer and using its contents to print it to the output.
What your program does:
The extra \n characters are probably added by the system. Beware that \n does not flush the output buffer, you have to call the flushing function to be sure a flush has occurred.