说明

这里基于 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 代码是一样的,也要定义、调用等步骤。

PHP 语法字符串函数 strcmp、strlen 使用及实现的更多相关文章

  1. 实现字符串函数,strlen(),strcpy(),strcmp(),strcat()

    实现字符串函数,strlen(),strcpy(),strcmp(),strcat() #include<stdio.h> #include<stdlib.h> int my_ ...

  2. 字符串函数---strcmp()与strncmp()具体解释及实现

    一.strcmp()与strncmp() strcmp():strcmp(s1,s2);            比較两个字符串.        strncmp():strncmp(s1,s2);   ...

  3. 字符串函数---strcmp()与strncmp()详解及实现【转】

    本文转载自:http://blog.csdn.net/lanzhihui_10086/article/details/39829623 一.strcmp()与strncmp() strcmp():st ...

  4. PHP基础语法: echo,var_dump, 常用函数:随机数:拆分字符串:explode()、rand()、日期时间:time()、字符串转化为时间戳:strtotime()可变参数的函数:PHP里数组长度表示方法:count($attr[指数组]);字符串长度:strlen($a)

    PHP语言原理:先把代码显示在源代码中,再通过浏览器解析在网页上 a. 1.substr;  //用于输出字符串中,需要的某一部分 <?PHP $a="learn php"; ...

  5. Linux C 字符串函数 strlen()、strcat()、strncat()、strcmp()、strncmp()、strcpy()、strncpy() 详解

      strlen(返回字符串长度) 表头文件 #include <string.h> 定义函数 size_t strlen(const char *s); 函数说明 strlen()用来计 ...

  6. Strcmp(字符串1,字符串2)函数 Sizeof && strlen() Substr(a,b)

    Strcmp(字符串1,字符串2)函数 { strcmp函数是比较两个字符串的大小,返回比较的结果.一般形式是:  i=strcmp(字符串,字符串); 其中,字符串1.字符串2均可为字符串常量或变量 ...

  7. 字符串函数(strcpy字符串拷,strcmp字符串比较,strstr字符串查找,strDelChar字符串删除字符,strrev字符串反序,memmove拷贝内存块,strlen字符串长度)

    1.strcpy字符串拷贝拷贝pStrSource到pStrDest,并返回pStrDest地址(源和目标位置重叠情况除外) char *strcpy(char *pStrDest, const ch ...

  8. 内存及字符串操作篇strlen strchar strcmp strcoll strcpy strdup strstr strtok strspn strrchr bcmp bcopy bzero index memccpy memset

    bcmp(比较内存内容) 相关函数 bcmp,strcasecmp,strcmp,strcoll,strncmp,strncasecmp 表头文件 #include<string.h> 定 ...

  9. C语言-字符串函数的实现(一)之strlen

    C语言中的字符串函数有如下这些 获取字符串长度 strlen 长度不受限制的字符串函数 strcpy strcat strcmp 长度受限制的字符串函数 strncpy strncat strncmp ...

随机推荐

  1. fastai 官方教程之查看数据

    本文为fastai官方教程编译版本.若有错误,欢迎指正. 总目录: *查看数据:本节为初级教程,介绍怎样快速的查看你的数据和模型预测结果.* 推理学习器(Inference Learner):本节为中 ...

  2. 探索学习率设置技巧以提高Keras中模型性能 | 炼丹技巧

      学习率是一个控制每次更新模型权重时响应估计误差而调整模型程度的超参数.学习率选取是一项具有挑战性的工作,学习率设置的非常小可能导致训练过程过长甚至训练进程被卡住,而设置的非常大可能会导致过快学习到 ...

  3. 机器学习算法系列:FM分解机

    在线性回归中,是假设每个特征之间独立的,也即是线性回归模型是无法捕获特征之间的关系.为了捕捉特征之间的关系,便有了FM分解机的出现了.FM分解机是在线性回归的基础上加上了交叉特征,通过学习交叉特征的权 ...

  4. Unity 阴影淡入淡出效果中Shader常量 unity_ShadowFadeCenterAndType和_LightShadowData的问题

    由于Universal Render Pipeline目前(2020年4月1日)把阴影淡入淡出这个功能竟然给取消了…我自己拿片元位置到相机位置的距离进行了一个淡化,但是阴影边缘老是被裁切…后来研究了一 ...

  5. Ubuntu查看文件格式(后缀名)

    在文件目录执行: $ file filename #filename表示要查看的文件名

  6. 模块 jieba结巴分词库 中文分词

    jieba结巴分词库 jieba(结巴)是一个强大的分词库,完美支持中文分词,本文对其基本用法做一个简要总结. 安装jieba pip install jieba 简单用法 结巴分词分为三种模式:精确 ...

  7. java web综合案例

    1.采用的技术: bootstrap+jsp+servlet+三层架构(servlet,service,dao)+mysql 注意:mysql使用的是5.5版本,使用高版本会有很多问题.可以将5.5版 ...

  8. Mac OS安装Go语言及配置VSCode开发环境:一个工具(gopls)解千愁

    前言 截止到目前为止,Go语言已经更新到1.14.1,网上的很多教程均已经过时,我在此汇总并整理一下相关的教程,提供一个适合当下的Mac OS教程. 教程中使用了Go在1.11之后推出的依赖包管理工具 ...

  9. UITextFiled-集合目录

    键盘弹起遮挡输入输入框(UITextFiled或者UITextView)                   对于键盘弹起遮挡输入框的问题以前也想过解决办法比如:监听系统键盘弹出通知.根据每个控件所在 ...

  10. RocketMQ 源码分析之路由中心(NameServer)

    你可能没有看过 RocketMQ 的架构图,没关系,一起来学习一下,RocketMQ 架构图如下: 在 RocketMQ 中,有四个角色: Producer:消息的生产者,每个 MQ 中间件都有. C ...