printf-ing非0终止字符串时使用percison的可移植性

正如这里的多个问题也指出的那样,您可以printf通过将精度设置为要打印的最大长度来格式化未终止的字符串。就像是

printf("%.*sn", length, str);

将打印length开始于str(或直到第一个 0 字节)的字符。

正如jonathan-leffler在此处指出的,这是由 posix here指定的。在阅读文档时,我发现它实际上从未说明这应该起作用(或者我找不到它),因为“ '%s' 转换会打印一个字符串。 ”和“一个字符串是一个以空字符结尾的字节数组 [ ...] ”。关于精度的注意事项说明“可以指定精度以指示要写入的最大字符数; ”。

我的解释是,上面的行实际上是未定义的行为,但是由于printf的实现是有效的,它不会读取写入更多的内容。

所以我的问题是:这种解释是否正确?

TLDR:当我尝试兼容 posix 时,我是否应该停止使用这个 printf 技巧,因为存在可能导致缓冲区溢出的实现?

回答

您正在阅读的不是实际的 POSIX 规范,而是 GNU libc 手册,为了可读性,该手册往往不太精确。实际的规范可以在https://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html找到(它甚至从你链接到的 Jonathan Leffler 的答案中链接),它清楚地表明你的代码很好:

s
参数应该是一个指向字符数组的指针。数组中的字节应写入(但不包括)任何终止空字节。如果指定了精度,则写入的字节数不得超过该数量。如果精度未指定或大于数组的大小,应用程序应确保数组包含空字节。

请注意,他们非常小心,不会因为您指出的原因而使用“字符串”一词。

ISO C17 标准使用几乎相同的语言,因此您的代码甚至可以移植到非 POSIX 标准 C 实现。(POSIX 通常包含 ISO C,并且 POSIX 规范的许多部分是从 C 标准复制/粘贴的。)


以上是printf-ing非0终止字符串时使用percison的可移植性的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>