Где находится исходный код функции strlen () в PHP? - PullRequest
4 голосов
/ 09 февраля 2020

Я просматривал php-src/Zend/zend_API.c и не мог найти исходный код для функции strlen() в PHP. Пролистывание базы кода не очень помогло, так как везде было полно lib c strlen. Гугл тоже не сильно помогает.

Я пытался использовать расширение Vulcan Logi c 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                                         $0      
         5        ECHO                                                     $0
         6      > RETURN                                                   1

Обратите внимание, как strpos() отображается как вызов функции, но не strlen(). Поэтому я попробовал это ( это на 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                                         $3      
         7        ECHO                                                     $3
         8      > RETURN                                                   1

Обратите внимание, как внезапно STRLEN появляется в списке операций, но, как ни странно, strpos() отображается как INIT_FCALL. Похоже, что-то в strlen() отличается от других функций. Я попытался просмотреть руководство, чтобы лучше понять, как работают коды операций , но зашел в тупик, так как там не так много полезной информации.


Может кто-нибудь объяснить, почему strlen() кажется вести себя так, как другие функции, и, возможно, указать мне исходный код для этого? Возможно, причина, по которой я не могу найти его источник, может быть связана с тем, почему он такой особенный? Я не уверен.

1 Ответ

6 голосов
/ 09 февраля 2020

strlen() на самом деле является кодом операции в PHP 7 и поэтому не ведет себя как типичная функция. Его исходный код находится в php-src/Zend/zend_string.h в строке 53 (на момент написания этой статьи), которая определяется как макрос.

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

В основном это просто чтение len член _zend_string struct , которая хранит длину строки в качестве члена.

Если вы посмотрите на git -blame , вы Вы увидите, что этот конкретный макрос был добавлен во время выпуска PHP 7 в 2015 году.

Вот коммит: 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() превратился из функции в код операции, или это всегда был код операции.

Однако я вижу, как может внутренняя строка повлиять на вывод Vulcan в вашем эксперименте. Если вы используете интернированную строку, PHP, похоже, использует какой-то ярлык в исполнителе по какой-то причине. Мне неясно, как именно, но да, похоже, он ведет себя несколько иначе, чем типичная функция.

...