解释
这里基于php7.2.5进行测试,php7之后内部构造变革该当不是太大,但与php5.X有差别。
我们接上一篇每天一个PHP语法-变量利用及内部实现再来说一下字符串内置函数的实现。
函数分类
用户自定义函数
say();function say(){ echo "周杰伦";}
php hello.php周杰伦
cli模式下我们实行这个代码之后就会输出函数调用的结果,大略来说这个过程经历了下面的步骤
我们可以先理解为要经历编译、实行两步。也便是我们每次实行这段代码都要经历这样的一个过程。
内置函数
也便是我们在手册中看到的函数,太多了,这里我们用字符串函数来举例解释。与用户自定义函数不同,内置函数不须要经历编译,直接定义注册就可以。
以是内置函数的效率相对是高一些。
函数如何实现的
strlen("hello"); // 这个语法不说了,返回字符串长度
// Zend/zend_builtin_functions.cZEND_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则即是0strcmp("ha", "h");// 1 多一个字符//=====strcmp("ha","hA");// 32 这个32是咋来的呢, ASCIIecho ord("A"); // 65echo PHP_EOL;echo ord("a"); // 97
// 来看实现 // 定义函数 ZEND_FUNCTION(strcmp){ // 参数 s1=ha, s2=hzend_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的长度lenRETURN_LONG(zend_binary_strcmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2)));}// 来看zend_binary_strcmpZEND_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代码是一样的,也要定义、调用等步骤。