PHP中strlen()函数的源代码在哪里?

Where is the source code for strlen() function in PHP?

我正在查看 php-src/Zend/zend_API.c,但在任何地方都找不到 PHP 中 strlen() 函数的 源代码 。遍历代码库并没有真正帮助,因为它到处都是 libc strlen。谷歌搜索也没有太大帮助。

我尝试使用 Vulcan Logic Dumper 扩展来检查幕后发生的事情。

我尝试了以下代码作为测试:

<?php

strlen("foo"); strpos("foo", "f");

这是我得到的:

Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /tmp/test.php
function name:  (null)
number of ops:  7
compiled vars:  none
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   3     0  E >   ECHO                                                     3
   4     1        INIT_FCALL                                               'strpos'
         2        SEND_VAL                                                 'foo'
         3        SEND_VAL                                                 'o'
         4        DO_ICALL                                         [=23=]      
         5        ECHO                                                     [=23=]
         6      > RETURN                                                   1

请注意 strpos() 如何显示为函数调用,而不是 strlen()。所以我尝试了这个(this on PHP 7.4,顺便说一句)作为一个实验,得到了一些有趣的东西。

代码

<?php
$str = "foo";

echo strlen($str);
echo strpos($str, "o");

Vulcan 的输出

Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /tmp/test2.php
function name:  (null)
number of ops:  9
compiled vars:  !0 = $str
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   2     0  E >   ASSIGN                                                   !0, 'foo'
   4     1        STRLEN                                           ~2      !0
         2        ECHO                                                     ~2
   5     3        INIT_FCALL                                               'strpos'
         4        SEND_VAR                                                 !0
         5        SEND_VAL                                                 'o'
         6        DO_ICALL                                               
         7        ECHO                                                     
         8      > RETURN                                                   1

请注意 STRLEN 是如何突然出现在操作列表中的,但奇怪的是 strpos() 却显示为 INIT_FCALLstrlen() 似乎与其他函数有所不同。我尝试了 looking through the manual to better understand how the opcodes 工作,但由于没有太多有用的信息而陷入了死胡同。


任何人都可以解释为什么 strlen() 的行为似乎与其他函数如此不同,也许可以向我指出它的源代码?也许我无法找到它的来源的原因可能与它如此特别的原因有关?我不确定。

strlen() 实际上是 PHP 7 中的一个操作码,因此表现得不像一个典型的函数。它的源代码位于php-src/Zend/zend_string.h第53行(截至撰写本文时),它被定义为一个宏。

#define ZSTR_LEN(zstr)  (zstr)->len

基本上就是读取_zend_string structlen成员,将字符串的长度存储为成员。

如果您查看 git-blame,您会发现该特定宏是在 2015 年 PHP 7 发布时添加的。

这是提交:https://github.com/php/php-src/commit/4bd22cf1c1d6a262fe2f026e082f2565433c53df

这是我的 git 日志中的内容:

commit 4bd22cf1c1d6a262fe2f026e082f2565433c53df
Author: Dmitry Stogov 
Date:   Mon Jun 29 16:44:54 2015 +0300

    Improved zend_string API (Francois Laupretre)

    Squashed commit of the following:

    commit d96eab8d79b75ac83d49d49ae4665f948d15a804
    Author: Francois Laupretre 
    Date:   Fri Jun 26 01:23:31 2015 +0200

        Use the new 'ZSTR' macros in the rest of the code.

        Does not change anything to the generated code (thanks to compat macros) but cleaner.

    commit b3526439104ac7a89a8e0c79dbebf33b22bd01b8
    Author: Francois Laupretre 
    Date:   Thu Jun 25 13:45:06 2015 +0200

        Improve zend_string API

        Add missing methods

所以看起来 PHP 7 发布前后的某个时候对 API 进行了一些改进。目前还不清楚这是否意味着 strlen() 从一个函数变成了一个操作码,或者它是否一直是一个操作码。

不过,我确实看到 interned string 内容可能会如何影响 Vulcan 在您的实验中的输出。如果您使用实习字符串 PHP 似乎出于某种原因在执行程序中采用了某种快捷方式。我不清楚具体如何,但是是的,它的行为似乎与典型函数有些不同。