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

Deadly 提交于 2020-04-06 08:50:37

问题


I was looking through php-src/Zend/zend_API.c and couldn't find the source code for the strlen() function in PHP anywhere. Grepping through the code base didn't really help as it's littered with libc strlen everywhere. Googling doesn't much help either.

I tried using the Vulcan Logic Dumper extension to inspect what's going on under the hood.

I tried the following code as a test:

<?php

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

This is what I got:

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                                         $0      
         5        ECHO                                                     $0
         6      > RETURN                                                   1

Notice how strpos() shows up as a function call, but not strlen(). So I tried this (this on PHP 7.4, by the way) as an experiment and got something interesting.

Code

<?php
$str = "foo";

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

Output from 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                                         $3      
         7        ECHO                                                     $3
         8      > RETURN                                                   1

Notice how all of a sudden STRLEN shows up in the op list, but strangely enough strpos() shows up as INIT_FCALL. Seems like something's different about strlen() than other functions. I tried looking through the manual to better understand how the opcodes work, but hit a dead end as not much useful information is there.


Can anyone explain why strlen() seems to behave so different than other functions and perhaps point me to the source code for it? Perhaps the reason I cannot seem to find its source might have something to do with why it's so special? I'm not sure.


回答1:


strlen() is actually an opcode in PHP 7 and thus doesn't behave like a typical function. Its source code is located in php-src/Zend/zend_string.h on line 53 (as of the time of this writing), which is defined as a Macro.

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

It's basically just reading the len member of the _zend_string struct, which stores the length of the string as a member.

If you look at the git-blame you'll see that particular macro was added around the time of PHP 7's release in 2015.

Here's the commit: https://github.com/php/php-src/commit/4bd22cf1c1d6a262fe2f026e082f2565433c53df

Here's what my git log says:

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

So it looks like at some point around PHP 7's release some improvements were made to the API. It's unclear if this means strlen() went from being a function to being an opcode, or if it was always an opcode.

I do see, though, how the interned string stuff might effect the output of Vulcan in your experiment. If you use an interned string PHP seems to take some kind of shortcut in the executor for some reason. I'm unclear as to how, exactly, but yes it does appear to behave somewhat differently from a typical function.



来源:https://stackoverflow.com/questions/60134074/where-is-the-source-code-for-strlen-function-in-php

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!