Table des matières
深入php内核之php in array,phparray
Maison php教程 php手册 深入php内核之php in array,phparray

深入php内核之php in array,phparray

Jun 13, 2016 am 08:51 AM
array in php Noyau

深入php内核之php in array,phparray

先给大家介绍php in array函数基本知识热热身。

定义和用法

in_array() 函数在数组中搜索给定的值。

语法
in_array(value,array,type)

参数 描述
value 必需。规定要在数组搜索的值。
array 必需。规定要搜索的数组。
type 可选。如果设置该参数为 true,则检查搜索的数据与数组的值的类型是否相同。

 说明

如果给定的值 value 存在于数组 array 中则返回 true。如果第三个参数设置为 true,函数只有在元素存在于数组中且数据类型与给定值相同时才返回 true。

如果没有在数组中找到参数,函数返回 false。

注释:如果 value 参数是字符串,且 type 参数设置为 true,则搜索区分大小写。

无意中看到一段代码

<&#63;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;
 } 
}
Copier après la connexion

测试了一下

[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); 
}                
/* }}} */ 
Copier après la connexion

顺便看到了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 */
Copier après la connexion

我们发现 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;
}  
/* }}} */
Copier après la connexion

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)&#63;1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)&#63;-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) &#63; -1 : 0);
   return SUCCESS;
   case TYPE_PAIR(IS_BOOL, IS_NULL):
   ZVAL_LONG(result, Z_LVAL_P(op1) &#63; 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) &#63; -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) &#63; 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;
   }
  } 
 }  
}   
/* }}} */
Copier après la connexion

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Comment déverrouiller tout dans Myrise
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Guide d'installation et de mise à niveau de PHP 8.4 pour Ubuntu et Debian Guide d'installation et de mise à niveau de PHP 8.4 pour Ubuntu et Debian Dec 24, 2024 pm 04:42 PM

PHP 8.4 apporte plusieurs nouvelles fonctionnalités, améliorations de sécurité et de performances avec une bonne quantité de dépréciations et de suppressions de fonctionnalités. Ce guide explique comment installer PHP 8.4 ou mettre à niveau vers PHP 8.4 sur Ubuntu, Debian ou leurs dérivés. Bien qu'il soit possible de compiler PHP à partir des sources, son installation à partir d'un référentiel APT comme expliqué ci-dessous est souvent plus rapide et plus sécurisée car ces référentiels fourniront les dernières corrections de bogues et mises à jour de sécurité à l'avenir.

Date et heure de CakePHP Date et heure de CakePHP Sep 10, 2024 pm 05:27 PM

Pour travailler avec la date et l'heure dans cakephp4, nous allons utiliser la classe FrozenTime disponible.

Téléchargement de fichiers CakePHP Téléchargement de fichiers CakePHP Sep 10, 2024 pm 05:27 PM

Pour travailler sur le téléchargement de fichiers, nous allons utiliser l'assistant de formulaire. Voici un exemple de téléchargement de fichiers.

Discuter de CakePHP Discuter de CakePHP Sep 10, 2024 pm 05:28 PM

CakePHP est un framework open source pour PHP. Il vise à faciliter grandement le développement, le déploiement et la maintenance d'applications. CakePHP est basé sur une architecture de type MVC à la fois puissante et facile à appréhender. Modèles, vues et contrôleurs gu

CakePHP créant des validateurs CakePHP créant des validateurs Sep 10, 2024 pm 05:26 PM

Le validateur peut être créé en ajoutant les deux lignes suivantes dans le contrôleur.

Journalisation CakePHP Journalisation CakePHP Sep 10, 2024 pm 05:26 PM

Se connecter à CakePHP est une tâche très simple. Il vous suffit d'utiliser une seule fonction. Vous pouvez enregistrer les erreurs, les exceptions, les activités des utilisateurs, les actions entreprises par les utilisateurs, pour tout processus en arrière-plan comme cronjob. La journalisation des données dans CakePHP est facile. La fonction log() est fournie

Comment configurer Visual Studio Code (VS Code) pour le développement PHP Comment configurer Visual Studio Code (VS Code) pour le développement PHP Dec 20, 2024 am 11:31 AM

Visual Studio Code, également connu sous le nom de VS Code, est un éditeur de code source gratuit – ou environnement de développement intégré (IDE) – disponible pour tous les principaux systèmes d'exploitation. Avec une large collection d'extensions pour de nombreux langages de programmation, VS Code peut être c

Guide rapide CakePHP Guide rapide CakePHP Sep 10, 2024 pm 05:27 PM

CakePHP est un framework MVC open source. Cela facilite grandement le développement, le déploiement et la maintenance des applications. CakePHP dispose d'un certain nombre de bibliothèques pour réduire la surcharge des tâches les plus courantes.

See all articles