手册说
成功返回后,这些函数[printf,dprintf等]将返回打印的字符数。
手册不提及这个数字可能比“最终”(替换和格式化完成)字符串的长度少(但是非负)。也没有提到如何检查(或实现)字符串是否完全写。
dprintf函数对文件描述符进行操作。类似于写函数,手册 提及
成功时,返回写入的字节数(零表示没有写入)。如果此数字小于请求的字节数,则不是错误;
因此,如果我想完全写一个字符串,那么我必须将n = write()
括在一个while循环中。在 dprintf 或 printf 的情况下,我是否必须这样做?
答案 0 :(得分:2)
我对documentation的理解是dprintf
会失败或输出所有输出。但我同意这是一些灰色地带(我可能不太了解);我猜测部分输出是某种失败(因此返回负值)。
以下是musl-libc的实施:
在stdio/dprintf.c dprintf
功能只调用vdprintf
但在stdio/vdprintf.c你只有:
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
输出到某个内存缓冲区,并在该缓冲区上明确使用write(2)。
查看stdio/__stdio_write.c __stdio_write
的实现(它在循环中使用带有两个数据块的向量的writev(2))。
换句话说,我常常不在乎;但是如果你真的需要确保每个字节都按照你的预期写入(例如,如果文件描述符是某个HTTP套接字),我建议缓冲显式(例如通过调用{{ 1}}和/或snprintf
)您自己,然后使用您明确的write(2)。
PS。您可以自己检查提供asprintf
的您的特定C标准库的源代码;对于GNU glibc,请参见libio/iovdprintf.c
答案 1 :(得分:1)
使用stdio,返回部分写入的字节数并没有多大意义,因为stdio函数可以使用(或多或少)全局缓冲区,其状态是未知的,并且从之前的调用中被拖入。
如果stdio函数允许你使用它,那么错误返回值将需要更复杂,因为它们不仅需要传达已输出或未输出的字符数,而且还需要在上次输入之前确认失败在缓冲区的某个地方,或者在上次输入的中间,如果是这样,最后输入的缓冲量是多少。
理论上,d函数可以很容易地为你提供部分写入字符的数量,但POSIX指定它们应该镜像stdio函数,因此它们只会在错误时给你一个未指定的负值。
如果您需要更多控制,可以使用较低级别的功能。
答案 2 :(得分:1)
关于printf()
,很明显。
printf
函数返回传输的字符数,如果发生输出或编码错误则返回负值。 C11dr§7.21.6.33
如果发生错误,则返回负值。在这种情况下,可能已打印了0个或更多字符。通过标准库无法知晓计数。
如果值返回不为负数,则为发送到stdout
的数字。
由于stdout
经常被缓冲,因此可能不是printf()
结束时输出设备上收到的数字。使用printf()
fflush(stdout)
int r1 = printf(....);
int r2 = fflush(stdout);
if (r1 < 0 || r2 != 0) Handle_Failure();
要进行最精细的控制,请“打印”到缓冲区并使用putchar()
或各种非标准功能。
答案 3 :(得分:0)
我打赌不。 (在查看 printf 的 - 混淆 - 来源之后。)所以任何非负返回值意味着printf 完全成功(到达结束时)格式字符串,一切都传递给内核缓冲区) 但是一些(真实的)人应该确认它。