您的位置 首页 php

每天一个PHP语法三字符串函数strcmp、strlen使用及实现

说明

这里基于php7.2.5进行测试,php7之后内部结构变化应该不是太大,但与php5.X有差别。

我们接上一篇 再来说一下字符串内置函数的实现。

函数分类

用户自定义函数

 say();

function say()
{
    echo " 周杰伦 ";
}
  
 php hello.php

周杰伦  

cli模式下我们执行这个代码之后就会输出函数调用的结果,简单来说这个过程经历了下面的步骤

我们可以先理解为要经历编译、执行两步。也就是我们每次执行这段代码都要经历这样的一个过程。

内置函数

也就是我们在手册中看到的函数,太多了,这里我们用字符串函数来举例说明。与用户自定义函数不同,内置函数不需要经历编译,直接定义注册就可以。

所以内置函数的效率相对是高一些。

函数如何实现的

 strlen("hello"); // 这个语法不说了,返回字符串长度  
 // Zend/zend_builtin_functions.c

ZEND_FUNCTION(strlen) // 定义函数 strlen是函数名
{
zend_string *s; // 这是参数字符串

ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_STR(s)
ZEND_PARSE_PARAMETERS_END();

RETVAL_LONG(ZSTR_LEN(s));// 主要看这里 给返回值设置的是 s的长度
}


// 来看下ZSTR_LEN是啥
// zend_string.h

#define ZSTR_LEN(zstr)  (zstr)->len // 很巧返回的是zend_value.zend_string.len 记得吗

// RETVAL_LONG 函数 给返回值赋值也就是 len 字符串的长度,并把返回值的类型设置为 IS_LONG
  

小结

可以看到strlen其实是直接获取了zval.zend_value.zend_string.len, 最后一步是把len赋值给函数返回值。

这里需要说明的是

  • ZEND_FUNCTION是函数声明的通用格式,知道就行。
  • 函数返回值也是一个变量,函数执行完返回它。

 strcmp($str1, $str2);
//这个函数是比较两个字符串的大小,如果str1>str2则大于0,如果str1<str2则小于0,如果str1=str2则等于0


strcmp("ha", "h");// 1 多一个字符

//=====

strcmp("ha","hA");// 32 这个32是咋来的呢, ASCII

echo ord("A"); // 65
echo PHP_EOL;
echo ord("a"); // 97  
 // 来看实现  
// 定义函数  
ZEND_FUNCTION(strcmp)
{
  // 参数 s1=ha, s2=h
zend_string *s1, *s2;

  // 这里设置参数
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_STR(s1)
Z_PARAM_STR(s2)
ZEND_PARSE_PARAMETERS_END();

  // 这里进行比较, 调用zend_binary_strcmp进行比较
  // 参数为s1的值也就是ha, s1的长度也就是2, s2的值h, s2的长度 1
  // ZSTR_LEN() 看上面,返回s1的长度len
RETURN_LONG(zend_binary_strcmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2)));
}



// 来看zend_binary_strcmp

ZEND_API int ZEND_FASTCALL zend_binary_strcmp(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */{
  // 返回值
int retval;

  // 如果完全相等就是0, == 在任何语言都适合
if (s1 == s2) {
return 0;
}
  // 调用c内置函数memcmp比较
  // min(len1, len2) 是获取最短的那个长度
  // 如min("ha", "h") 就比较前1个字符
retval = memcmp(s1, s2, MIN(len1, len2));
  // 如果=0则再min长度内是相等的,返回值就是哪个长就返回多出来的字符数
if (!retval) {
return (int)(len1 - len2);
} else {
    // 如果<>0,则就返回那个值
return retval;
}
}

// 关于memcmp 在c官方手册看到 , 比较两个字符串,s1>s2返回大于0,s1<s2返回小于0, s1=s2返回0
// 参考
// 就是把每个字符都比较一遍
int memcmp(const void *s1, const void *s2, size_t n){
    const unsigned char *su1, *su2;
    for(su1 = s1, su2 = s2; 0 < n; ++su1, ++su2, --n)
        if(*su1 != *su2)
            return ((*su1 < *su2) ? -1 : +1);
    return 0;

}  

小结

strcmp的实现是基于C内置函数memcmp实现的,规则就是memcmp的语法。

总结

内置函数不需要经历编译过程,执行速度比自定义函数要快,实现上跟我们写PHP代码是一样的,也要定义、调用等步骤。

文章来源:智云一二三科技

文章标题:每天一个PHP语法三字符串函数strcmp、strlen使用及实现

文章地址:https://www.zhihuclub.com/152614.shtml

关于作者: 智云科技

热门文章

网站地图