正如这里的多个问题所指出的那样,您可以printf
通过精确格式化作为要打印的最大长度来设置非终止字符串。就像是
printf("%.*s\n", length, str);
将打印length
从str
(或直到第一个0字节)的字符。
正如jonathan-leffler在这里指出的,这由posix在此处指定。而且当我阅读文档时,我发现它实际上从未声明过应该工作(或者我找不到),因为“ '%s'转换会打印一个字符串。 ”和“字符串是一个以空值终止的字节数组[ ...] ”。“关于精度状态下的方面可以被指定的精度,以指示字符的最大数目的写入; ”。
我的解释是,上面的代码行实际上是未定义的行为,但是由于printf
的实现是高效的,因此读取的内容并不多于写入的内容。
所以我的问题是:这种解释正确吗?
TLDR:由于要实现posix兼容,我是否应该停止使用此printf技巧,因为存在可能导致缓冲区溢出的实现?
您所阅读的不是真正的POSIX规范,而是GNU libc手册,出于可读性考虑,该手册的精确度往往有所降低。实际的规范可以在https://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html上找到(它甚至与您链接到的Jonathan Leffler的答案链接),而且很清楚您的代码很好:
s
该参数应为指向char数组的指针。数组中的字节应被写入(但不包括)任何终止的空字节。如果规定了精度,则写入的字节数不得超过该字节数。如果未指定精度或大于数组的大小,则应用程序应确保该数组包含一个空字节。
请注意,出于您指出的确切原因,他们要小心不要使用单词“字符串”。
ISO C17标准使用几乎相同的语言,因此您的代码甚至可以移植到非POSIX标准C实现中。(POSIX通常包含ISO C,并且POSIX规范的许多部分都是从C标准复制/粘贴的。)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句