深入php内核之php in array
发布:smiling 来源: PHP粉丝网 添加日期:2021-06-26 14:03:39 浏览: 评论:0
这篇文章主要介绍了深入php内核之php in array的相关资料,需要的朋友可以参考下,先给大家介绍php in array函数基本知识热热身。
定义和用法
in_array() 函数在数组中搜索给定的值。
语法
in_array(value,array,type)
参数 描述
value 必需。规定要在数组搜索的值。
array 必需。规定要搜索的数组。
type 可选。如果设置该参数为 true,则检查搜索的数据与数组的值的类型是否相同。
说明
如果给定的值 value 存在于数组 array 中则返回 true。如果第三个参数设置为 true,函数只有在元素存在于数组中且数据类型与给定值相同时才返回 true。
如果没有在数组中找到参数,函数返回 false。
注释:如果 value 参数是字符串,且 type 参数设置为 true,则搜索区分大小写。
无意中看到一段代码:
- <?php
- $y="1800";
- $x = array();
- for($j=0;$j<50000;$j++){
- $x[]= "{$j}";
- }
- for($i=0;$i<30000;$i++){
- if(in_array($y,$x)){
- continue;
- }
- }
测试了一下
- [root@dev tmp]# time php b.php
- real 0m9.517s
- user 0m4.486s
- sys 0m0.015s
竟然需要9s
in_array是这个样子的,代码如下:
bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )
在 haystack 中搜索 needle,如果没有设置 strict 则使用宽松的比较。
needle
待搜索的值。如果 needle 是字符串,则比较是区分大小写的。
haystack
这个数组。
strict
如果第三个参数 strict 的值为 TRUE 则 in_array() 函数还会检查 needle 的类型是否和 haystack 中的相同。
那么我看一下源代码
第一步 在ext/standard/array.c 文件中
- /* }}} */
- /* {{{ proto bool in_array(mixed needle, array haystack [, bool strict])
- Checks if the given value exists in the array */
- PHP_FUNCTION(in_array)
- {
- php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
- }
- /* }}} */
- /* {{{ proto mixed array_search(mixed needle, array haystack [, bool strict])
- Searches the array for a given value and returns the corresponding key if successful */
- PHP_FUNCTION(array_search)
- {
- php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
- }
- /* }}} */
顺便看到了array_search,原来和in_array的内部实现基本一致,其中函数的参数 在./zend.h中
#define INTERNAL_FUNCTION_PARAM_PASSTHRU ht, return_value, return_value_ptr, this_ptr, return_value_used TSRMLS_CC
第二步 在ext/standard/array.c 文件中 查看php_search_array原型
- /* void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior)
- * 0 = return boolean
- * 1 = return key
- */
- static void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ */
- {
- zval *value, /* value to check for */
- *array, /* array to check in */
- **entry, /* pointer to array entry */
- res; /* comparison result */
- HashPosition pos; /* hash iterator */
- zend_bool strict = 0; /* strict comparison or not */
- ulong num_key;
- uint str_key_len;
- char *string_key;
- int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za|b", &value, &array, &strict) == FAILURE) {
- return;
- }
- if (strict) {
- is_equal_func = is_identical_function;
- }
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) {
- is_equal_func(&res, value, *entry TSRMLS_CC);
- if (Z_LVAL(res)) {
- if (behavior == 0) {
- RETURN_TRUE;
- } else {
- /* Return current key */
- switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &str_key_len, &num_key, 0, &pos)) {
- case HASH_KEY_IS_STRING:
- RETURN_STRINGL(string_key, str_key_len - 1, 1);
- break;
- case HASH_KEY_IS_LONG:
- RETURN_LONG(num_key);
- break;
- }
- }
- }
- zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos);
- }
- RETURN_FALSE;
- }
- /* }}} */
- /* {{{ proto bool in_array(mixed needle, array haystack [, bool strict])
- Checks if the given value exists in the array */
我们发现 strict 这个值的不同有两种比较方式,看一下两个函数的不同之处
is_identical_function 检查类型是否相同
- ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
- {
- Z_TYPE_P(result) = IS_BOOL;
- if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
- Z_LVAL_P(result) = 0;
- return SUCCESS;
- }
- switch (Z_TYPE_P(op1)) {
- case IS_NULL:
- Z_LVAL_P(result) = 1;
- break;
- case IS_BOOL:
- case IS_LONG:
- case IS_RESOURCE:
- Z_LVAL_P(result) = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- break;
- case IS_DOUBLE:
- Z_LVAL_P(result) = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- break;
- case IS_STRING:
- Z_LVAL_P(result) = ((Z_STRLEN_P(op1) == Z_STRLEN_P(op2))
- && (!memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1))));
- break;
- case IS_ARRAY:
- Z_LVAL_P(result) = (Z_ARRVAL_P(op1) == Z_ARRVAL_P(op2)
- zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0);
- break;
- case IS_OBJECT:
- if (Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2)) {
- Z_LVAL_P(result) = (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2));
- } else {
- Z_LVAL_P(result) = 0;
- }
- break;
- default:
- Z_LVAL_P(result) = 0;
- return FAILURE;
- }
- return SUCCESS;
- }
- /* }}} */
is_equal_function 不检查类型是否相同,所以需要隐式转换
- ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
- {
- if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
- return FAILURE;
- }
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
- return SUCCESS;
- }
- /* }}} */
- ==》compare_function
- ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
- {
- int ret;
- int converted = 0;
- zval op1_copy, op2_copy;
- zval *op_free;
- while (1) {
- switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
- case TYPE_PAIR(IS_LONG, IS_LONG):
- ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));
- return SUCCESS;
- case TYPE_PAIR(IS_DOUBLE, IS_LONG):
- Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2);
- ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
- return SUCCESS;
- case TYPE_PAIR(IS_LONG, IS_DOUBLE):
- Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2);
- ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
- return SUCCESS;
- case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
- if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) {
- ZVAL_LONG(result, 0);
- } else {
- Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
- ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
- }
- return SUCCESS;
- case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
- zend_compare_arrays(result, op1, op2 TSRMLS_CC);
- return SUCCESS;
- case TYPE_PAIR(IS_NULL, IS_NULL):
- ZVAL_LONG(result, 0);
- return SUCCESS;
- case TYPE_PAIR(IS_NULL, IS_BOOL):
- ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
- return SUCCESS;
- case TYPE_PAIR(IS_BOOL, IS_NULL):
- ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
- return SUCCESS;
- case TYPE_PAIR(IS_BOOL, IS_BOOL):
- ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
- return SUCCESS;
- case TYPE_PAIR(IS_STRING, IS_STRING):
- zendi_smart_strcmp(result, op1, op2);
- return SUCCESS;
- case TYPE_PAIR(IS_NULL, IS_STRING):
- ZVAL_LONG(result, zend_binary_strcmp("", 0, Z_STRVAL_P(op2), Z_STRLEN_P(op2)));
- return SUCCESS;
- case TYPE_PAIR(IS_STRING, IS_NULL):
- ZVAL_LONG(result, zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), "", 0));
- return SUCCESS;
- case TYPE_PAIR(IS_OBJECT, IS_NULL):
- ZVAL_LONG(result, 1);
- return SUCCESS;
- case TYPE_PAIR(IS_NULL, IS_OBJECT):
- ZVAL_LONG(result, -1);
- return SUCCESS;
- case TYPE_PAIR(IS_OBJECT, IS_OBJECT):
- /* If both are objects sharing the same comparision handler then use is */
- if (Z_OBJ_HANDLER_P(op1,compare_objects) == Z_OBJ_HANDLER_P(op2,compare_objects)) {
- if (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) {
- /* object handles are identical, apparently this is the same object */
- ZVAL_LONG(result, 0);
- return SUCCESS;
- }
- ZVAL_LONG(result, Z_OBJ_HT_P(op1)->compare_objects(op1, op2 TSRMLS_CC));
- return SUCCESS;
- }
- /* break missing intentionally */
- default:
- if (Z_TYPE_P(op1) == IS_OBJECT) {
- if (Z_OBJ_HT_P(op1)->get) {
- op_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC);
- ret = compare_function(result, op_free, op2 TSRMLS_CC);
- zend_free_obj_get_result(op_free TSRMLS_CC);
- return ret;
- } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) {
- ALLOC_INIT_ZVAL(op_free);
- if (Z_OBJ_HT_P(op1)->cast_object(op1, op_free, Z_TYPE_P(op2) TSRMLS_CC) == FAILURE) {
- ZVAL_LONG(result, 1);
- zend_free_obj_get_result(op_free TSRMLS_CC);
- return SUCCESS;
- }
- ret = compare_function(result, op_free, op2 TSRMLS_CC);
- zend_free_obj_get_result(op_free TSRMLS_CC);
- return ret;
- }
- }
- if (Z_TYPE_P(op2) == IS_OBJECT) {
- if (Z_OBJ_HT_P(op2)->get) {
- op_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC);
- ret = compare_function(result, op1, op_free TSRMLS_CC);
- zend_free_obj_get_result(op_free TSRMLS_CC);
- return ret;
- } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) {
- ALLOC_INIT_ZVAL(op_free);
- if (Z_OBJ_HT_P(op2)->cast_object(op2, op_free, Z_TYPE_P(op1) TSRMLS_CC) == FAILURE) {
- ZVAL_LONG(result, -1);
- zend_free_obj_get_result(op_free TSRMLS_CC);
- return SUCCESS;
- }
- ret = compare_function(result, op1, op_free TSRMLS_CC);
- zend_free_obj_get_result(op_free TSRMLS_CC);
- return ret;
- } else if (Z_TYPE_P(op1) == IS_OBJECT) {
- ZVAL_LONG(result, 1);
- return SUCCESS;
- }
- }
- if (!converted) {
- if (Z_TYPE_P(op1) == IS_NULL) {
- zendi_convert_to_boolean(op2, op2_copy, result);
- ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
- return SUCCESS;
- } else if (Z_TYPE_P(op2) == IS_NULL) {
- zendi_convert_to_boolean(op1, op1_copy, result);
- ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
- return SUCCESS;
- } else if (Z_TYPE_P(op1) == IS_BOOL) {
- zendi_convert_to_boolean(op2, op2_copy, result);
- ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
- return SUCCESS;
- } else if (Z_TYPE_P(op2) == IS_BOOL) {
- zendi_convert_to_boolean(op1, op1_copy, result);
- ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
- return SUCCESS;
- } else {
- zendi_convert_scalar_to_number(op1, op1_copy, result);
- zendi_convert_scalar_to_number(op2, op2_copy, result);
- converted = 1;
- }
- } else if (Z_TYPE_P(op1)==IS_ARRAY) {
- ZVAL_LONG(result, 1);
- return SUCCESS;
- } else if (Z_TYPE_P(op2)==IS_ARRAY) {
- ZVAL_LONG(result, -1);
- return SUCCESS;
- } else if (Z_TYPE_P(op1)==IS_OBJECT) {
- ZVAL_LONG(result, 1);
- return SUCCESS;
- } else if (Z_TYPE_P(op2)==IS_OBJECT) {
- ZVAL_LONG(result, -1);
- return SUCCESS;
- } else {
- ZVAL_LONG(result, 0);
- return FAILURE;
- }
- }
- }
- }
- /* }}} */
Tags: php内核 php in array
相关文章
- ·PHP内核探索之变量(2021-06-30)
- ·PHP内核探索之解释器的执行过程(2021-06-30)
- ·PHP内核学习教程之php opcode内核实现(2021-07-07)
- ·PHP中通过Web 执行C/C++应用程序(2013-11-13)
- ·用PHP实现Ftp用户的在线管理(2013-11-13)
- ·用PHP自动把纯文本转换成Web页面(2013-11-13)
- ·用实例分析PHP5异常处理(2013-11-13)
- ·php5的simplexml解析错误(2013-11-13)
- ·PHP后门的隐藏技巧测试报告(2013-11-13)
- ·PHP缓存技术详谈(2013-11-27)
- ·利用PHP自定义错误处理器处理出错信息(2013-11-27)
- ·PHP作wap开发时遇到的问题(2013-11-27)
- ·php编写大型网站问题集(2013-11-27)
- ·php测试性能代码(2013-11-28)
- ·php 安全register globals设置为TRUE的危害(2013-11-28)
- ·XSLTProcessor 中 registerPHPFunctions 后无法调用 php 函数(2013-11-30)
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)