zoukankan      html  css  js  c++  java
  • PHP 语法字符串函数 strcmp、strlen 使用及实现

    说明

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

    函数分类

     

    用户自定义函数

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

      

     

    php hello.php
    
    周杰伦
    

      

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

     

     

     

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

     

    内置函数

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

     

     

     

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

     

    函数如何实现的

    strlen

    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();
    // 主要看这里 给返回值设置的是 s的长度
        RETVAL_LONG(ZSTR_LEN(s));
    }
    
    // 来看下ZSTR_LEN是啥
    // zend_string.h
    // 很巧返回的是zend_value.zend_string.len 记得吗
    #define ZSTR_LEN(zstr)  (zstr)->len 
    // RETVAL_LONG 函数 给返回值赋值也就是 len 字符串的长度,并把返回值的类型设置为 IS_LONG
    

      

    小结

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

    这里需要说明的是:

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

    strcmp

    strcmp($str1, $str2);
    //这个函数是比较两个字符串的大小,如果str1>str2则大于0,如果str1<str2则小于0,如果str1=str2则等于0
    
    strcmp("ha", "h");// 1 多一个字符
    strcmp("ha","hA");// 32 这个32是咋来的呢,实际上如果字符数量相等则比较第二个字符的ASII值,看下面
    
    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
      // ZEND_LEN就是返回s2的长度,看上面的内容
        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 代码是一样的,也要定义、调用等步骤。

  • 相关阅读:
    springMVC,spring,mybatis全注解搭建框架--第一步,让框架跑起来
    实现excel导入导出功能,excel导入数据到页面中,页面数据导出生成excel文件
    不带插件 ,自己写js,实现批量上传文件及进度显示
    excel转html 实现在线预览
    word和.txt文件转html 及pdf文件, 使用poi jsoup itext心得
    实现图片旋转,滚动鼠标中间对图片放大缩小
    面试中常见问题之线程池与连接池的区别
    实例测试mysqlRR模式和RC模式各种锁情况
    分糖果
    MySQL试题
  • 原文地址:https://www.cnblogs.com/a609251438/p/12775205.html
Copyright © 2011-2022 走看看