大家都知道 libc 的 printf()
及其家族。本章节将详细介绍 PHP 声明和使用的许多克隆,它们的目标是什么,为什么使用它们,以及何时使用它们。
相关学习推荐:PHP编程从入门到精通
注意
Libc 中关于
printf()
及其朋友的文档位于此处。
你知道这些函数很有用,但有时无法提供足够的功能。另外,你知道向 printf()
添加格式字符串并非易事,没有便携性和有安全风险。
PHP 添加了自己的类似于 printf 的函数,取代了 libc 的,并且由内部开发者使用。他们主要添加新的格式,并使用 zend_string代替 char *
等等,让我们一起来看看。
警告
你必须掌握 libc 默认
printf()
格式。请阅读它们的文档。注意
添加了这些函数以 取代 libc 函数,意味着如果你使用了
sprintf()
,不会使用到 libc 的sprintf()
,而是 PHP 取代了。除了传统的printf()
外,其他内容均被替换。
传统用途
首先,你不应该使用 sprintf()
,因为该函数不执行任何检查,并且导致许多缓冲区溢出错误。请避免使用它。
警告
尽可能避免使用
sprintf()
。
然后,你有一些选择。
你知道结果缓冲区的大小
如果你知道缓冲区大小,snprintf()
或者 slprintf()
都可以使用。这些函数虽然在返回上不同,但是它们的功能是一样的。
这两个都是根据传递的格式来打印,并且无论发生什么,都会通过一个NUL
字节 ‘ ’来终止你的缓冲区。 但是,snprintf()
返回可以使用的字符数,而slprintf()
返回可以有效使用的字符数,因此可以检测过小的缓冲区和字符串截断。这个不会计算最后的‘ ’。
这里有个例子,以便你完全明白:
char foo[8]; /* 8字符大小的缓冲区 */ const char str[] = "Hello world"; /* 12个字符,包含 */ int r; r = snprintf(foo, sizeof(foo), "%s", str); /* r = 11 ,即使这里只有7个可打印的字符可写入 foo */ /* foo 的值现在是 'H' 'e' 'l' 'l' 'o' ' ' 'w' '