深入PHP核心之in_array

來源:互聯網
上載者:User
無意中看到一段代碼

測試了一下

[root@dev tmp]# time php b.php real    0m9.517suser    0m4.486ssys     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)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;            }      }        }         }             /* }}} */ 

以上就介紹了深入PHP核心之in_array,包括了方面的內容,希望對PHP教程有興趣的朋友有所協助。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.