这是我的计划:
#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'
是否正在刷新输出缓冲区并在以后被丢弃?
答案 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)
代码的问题在于您使用一个缓冲区来完成不同的任务 - 将其用作中间输出缓冲区并使用其内容将其打印到输出中。
你的计划做了什么:
额外\ n字符可能由系统添加。请注意\ n不会刷新输出缓冲区,您必须调用刷新函数以确保已发生刷新。