PHP判断字符串长度应直接使用O(1)的strlen(),递归不仅时间复杂度退化为O(n)、易栈溢出,且substr复制导致内存翻倍;需Unicode字符数时应改用mb_strlen()。

PHP 判断字符串长度根本不需要递归,strlen() 是内置的 O(1) 时间复杂度函数,直接返回字节数;递归测长不仅无意义,还会在长字符串上触发栈溢出或超时。
为什么 strlen() 不需要、也不该被递归替代
strlen() 底层直接读取 C 字符串的终止符 \0 位置,不遍历字符——它本身已是最优解。所谓“递归测长”只是教学演示陷阱,实际项目中等于主动引入 bug:
- 对 UTF-8 多字节字符(如中文)会返回字节数而非字符数,但这和递归无关,是编码问题
- 递归每层调用压栈,1000 字符就可能接近默认 2M 栈限制,
Segmentation fault或Fatal error: Maximum function nesting level - 时间复杂度从 O(1) 退化为 O(n),且常数倍远高于循环
真要手动测长?用循环,别用递归
如果出于学习目的想绕过 strlen(),应使用 while 或 for 循环——它可控、无栈风险、逻辑清晰:
$str = "hello世界";
$len = 0;
while (isset($str[$len])) {
$len++;
}
// $len === 11(UTF-8 字节数)
注意:$str[$i] 在 PHP 7.4+ 中是字节级访问,和 strlen() 行为一致;若需 Unicode 字符数(如“世界”算 2 个),必须用 mb_strlen($str, 'UTF-8')。
立即学习“PHP免费学习笔记(深入)”;
递归函数写出来会怎样?一个危险示例
下面这段代码看似“能跑”,但极度脆弱:
function str_len_recursive($s) {
if ($s === '') return 0;
return 1 + str_len_recursive(substr($s, 1));
}
// str_len_recursive(str_repeat('a', 10000)); // 很可能报错
问题不止于性能:每次 substr($s, 1) 都复制新字符串,内存占用翻倍;PHP 默认 xdebug.max_nesting_level=256,256 字符就中断;关闭 xdebug 后仍受系统栈限制。
真正该纠结的是编码——strlen() 和 mb_strlen() 的语义差异,而不是用不用递归。递归在这里没有存在价值,强行套用只会掩盖对底层机制的理解偏差。











