微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

打印非 0 终止字符串时使用 percison 的可移植性

如何解决打印非 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 举报,一经查实,本站将立刻删除。