我对标准C库中printf
的返回值和缓冲流的解释感到困惑。
在C99:TC3 Standard中,7.19.6.3 / p3定义printf
函数成功返回非负“字符数传输”。
此外,7.19.3 / p3描述了“传输到主机环境或从主机环境传输”的完全/线路缓冲流的行为,而p7表示stdout
可以是完全缓冲的流。
引用第7.19.3节,重点强调:
7.19.3档案
3当流 unbuffered 时,字符应尽快从源或目的地出现。否则,字符可以作为块累积并传输到主机环境或从主机环境传输。当流完全缓冲时,当填充缓冲区时,字符应作为块强制作为块传输到主机环境。 当流行缓冲时,当遇到换行符时,字符将作为块以传输到主机环境 。此外,当填充缓冲区,在无缓冲流上请求输入时,或者在需要使用缓冲流的行缓冲流上请求输入时,字符意图作为块传输到主机环境。从主机环境传输字符。对这些特性的支持是实现定义的,可能会受到
setbuf
和setvbuf
函数的影响。7 [...]最初打开时,标准错误流未完全缓冲;当且仅当可以确定流不参考交互设备时,标准输入和标准输出流是完全缓冲的。
这些定义导致以下行为是合法的。 但这是违反直觉和不可接受的结果(至少对我而言)。
#include <stdio.h>
#include <assert.h>
// PRECONDITION: `stdout` is fully buffered
int main()
{
int n = printf("abc"); // "abc" is accumulated, and no transmission.
assert(n == 0); // so, return value can be equal to 0 ??
}
我的解释错在哪里? 或者它只是“实现定义”行为中的一种?
答案 0 :(得分:2)
printf
和fprintf
的返回值是传输到流的字节数 - 它是主机环境中的对象 - 而不是最终目标。这些字节何时以及如何通过流传输到文件或设备(“从主机环境传输”)是无关紧要的。缓冲不会影响流如何从程序接受字节;只是在它持有它们之前,直到将它们发送到相关文件或设备上为止。
答案 1 :(得分:1)
“传输”一词意味着字节穿过某个接口。我认为7.19.6.3引用的接口是printf
和设备驱动程序之间的接口,而7.19.3引用的接口是设备驱动程序的输出。
此外,我认为你提出的解释会使printf
的返回值变得任意且反复无常。
因此,我得出结论,示例代码中的printf
将始终返回3.