如何解决打印非 0 终止字符串时使用 percison 的可移植性
正如这里的多个问题也指出的那样,您可以通过将精度设置为要打印的最大长度来 printf
一个未终止的字符串。类似的东西
printf("%.*s\n",length,str);
将从 length
开始(或直到第一个 0 字节)打印 str
个字符。
正如 jonathan-leffler 所指出的 here,这是由 posix here 指定的。在阅读文档时,我发现它实际上从未说明这应该起作用(或者我找不到它),例如“The ‘%s’ conversion prints a string.”和“A string is a null-terminated array of bytes [...] ”。关于精度的注意事项是“A precision can be specified to indicate the maximum number of characters to write;”。
我的解释是上面那行实际上是未定义的行为,但是因为 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 标准复制/粘贴的。)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。