C printf(或fprintf或dprintf)返回的“成功”数可能小于(但非负)的“成功”数;所有字节;?

C printf(或fprintf或dprintf)返回的“成功”数可能小于(但非负)的“成功”数;所有字节;?,c,printf,return-value,C,Printf,Return Value,手册上说 成功返回后,这些函数[printf、dprintf等]返回打印的字符数 手册没有提到这个数字是否比“最终”(替换和格式化完成)字符串的长度少(但不是负)。也没有提到如何检查(或实现)字符串是否已完全写入 dprintf函数对文件描述符进行操作。与写入功能类似,手册确实提到了这一点 成功时,返回写入的字节数(零表示未写入任何内容)。如果该数字小于请求的字节数,则不是错误 因此,如果我想完整地编写一个字符串,那么我必须将n=write()包含在while循环中。如果是dprintf或pri

手册上说

成功返回后,这些函数[printf、dprintf等]返回打印的字符数

手册没有提到这个数字是否比“最终”(替换和格式化完成)字符串的长度少(但不是负)。也没有提到如何检查(或实现)字符串是否已完全写入

dprintf函数对文件描述符进行操作。与写入功能类似,手册确实提到了这一点

成功时,返回写入的字节数(零表示未写入任何内容)。如果该数字小于请求的字节数,则不是错误

因此,如果我想完整地编写一个字符串,那么我必须将
n=write()
包含在while循环中。如果是dprintf或printf,我是否也必须这样做?

我对的理解是,
dprintf
将失败或输出所有输出。但我同意这是一个灰色地带(我可能不太理解);我猜部分输出是某种失败(因此返回负大小)

以下是实施:

dprintf
函数中,只调用
vdprintf

但在你身上,只有:

static size_t wrap_write(FILE *f, const unsigned char *buf, size_t len)
{
    return __stdio_write(f, buf, len);
}

int vdprintf(int fd, const char *restrict fmt, va_list ap)
{
    FILE f = {
        .fd = fd, .lbf = EOF, .write = wrap_write,
        .buf = (void *)fmt, .buf_size = 0,
        .lock = -1
    };
    return vfprintf(&f, fmt, ap);
}
因此
dprintf
返回的大小与
vfprintf
(和
fprintf
…)类似

但是,如果您真的担心,最好使用
snprintf
asprintf
输出到某个内存缓冲区,并显式地在该缓冲区上使用

查看
\uu stdio\u write
的实现(它使用循环中两个数据块的向量)

换言之,我通常不会真的在意;但是,如果您确实需要确保每个字节都按预期写入(例如,如果文件描述符是某个HTTP套接字),我建议您自己显式缓冲(例如,通过调用
snprintf
和/或
asprintf
),然后使用显式缓冲


另外,您可以检查您的特定C标准库的源代码,提供
dprintf
;对于GNU glibc,请参见stdio,返回部分写入的字节数没有多大意义,因为stdio函数使用的是(或多或少)全局缓冲区,其状态对您来说是未知的,并且从以前的调用中拖入

如果STDIO函数允许您使用该函数,则错误返回值将需要更复杂,因为它们不仅需要通信多少字符或未输出,而且还包括故障是否在缓冲区中的最后一个输入之前,或者在最后一个输入的中间,如果是,最后的输入中有多少得到缓冲

从理论上讲,d函数可以很容易地为您提供部分写入的字符数,但POSIX指定它们应该镜像stdio函数,因此它们只会在错误时为您提供进一步未指定的负值

如果需要更多控制,可以使用较低级别的函数。

关于
printf()
,这一点非常清楚

printf
函数返回传输的字符数,如果出现输出或编码错误,则返回负值。C11dr§7.21.6.3 3

如果发生错误,则返回负值。在这种情况下,可能打印了0个或更多字符。通过标准库,计数是未知的

如果返回值不是负值,则表示发送到标准输出的数字

由于
stdout
通常是缓冲的,因此在
printf()
的结论中,这可能不是输出设备接收到的数字。使用
fflush(stdout)

int r1=printf(..);
int r2=fflush(标准输出);
如果(r1<0 | | r2!=0)处理_故障();

为了实现最佳控制,“打印”到缓冲区,并使用
putchar()
或各种非标准函数。

我打赌没有。(在查看了printf的-obfuscated-source之后。)因此any非负返回值意味着printf是完全成功的(到达格式字符串的末尾,所有内容都被传递到内核缓冲区)。

但是一些(真实的)人应该对此进行确认。

如果您使用相同的格式说明符和参数第二次调用
printf
,您希望发生什么?返回值用于提供信息(或错误)。检查
printf
的正确输出的唯一方法是首先调用
sprintf
,但是
换行符的处理可能会有所不同。您的用例是什么?文件描述符的用途是什么?它有什么协议?
int r1 = printf(....);
int r2 = fflush(stdout);
if (r1 < 0 || r2 != 0) Handle_Failure();