Array pointers in php

PHP behavior and arrays pointers

The meaning of «pointer» in PHP arrays is not the same as the general meaning of «pointer» (in C/C++ or other languages that gives the programmer direct access to memory).,The pointer remains in the second array element (‘b’ => ‘banana’). This behavior is characteristic of language?,This behavior is characteristic of language?,As foreach relies on the internal array pointer, changing it within the loop may lead to unexpected behavior.

There are no pointers in PHP. The array data type keeps internally a cursor inside the list of values it contains. It is called the internal pointer of the array and it is modified by functions reset() , next() , prev() , end() , each() and maybe others. It can be used to iterate over the array like this:

$array = array(1, 2, 3); while (list($key, $val) = each($array)) < echo($key.' =>'.$val."\n"); > 

But this goal can be accomplished even easier using foreach() :

$array = array(0, 0, 0, 2, 0, 1, 0, 3); foreach ($array as $val) < if ($val != 0) < break; >> echo($val); // prints "2" 
$array = array(0, 0, 0, 2, 0, 1, 0, 3); do < $val = array_shift($array); if ($val != 0) < break; >> while(count($array)); echo($val); // prints "2" 

A simple test contradicts this statement:

$array = array(1, 3, 5, 7, 9); foreach ($array as $val1) < foreach ($array as $val2) < echo('$val1='.$val1.'; $val2='.$val2.'; '); >echo("\n"); > 

Answer by Gatlin Alexander

What References Are Not, References Explained , Predefined Interfaces and Classes

 Another example of something to watch out for when using references with arrays. It seems that even an usused reference to an array cell modifies the *source* of the reference. Strange behavior for an assignment statement (is this why I've seen it written as an =& operator? - although this doesn't happen with regular variables).Produces: Array ( [0] => 1 [1] => 22 // var_dump() will show the & here )I fixed my bug by rewriting the code without references, but it can also be fixed with the unset() function:Produces: Array ( [0] => 1 [1] => 2 ) 

Answer by Camden Bean

As foreach relies on the internal array pointer in PHP 5, changing it within the loop may lead to unexpected behavior. , In PHP 7, foreach does not use the internal array pointer. , In PHP 5, when foreach first starts executing, the internal array pointer is automatically reset to the first element of the array. This means that you do not need to call reset() before a foreach loop. , Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset(). Otherwise you will experience the following behavior:

foreach (array_expression as $value) statement foreach (array_expression as $key => $value) statement 

Answer by Davis Kline

Now, let’s look into the internal PHP array representation. The value field of “zval” with IS_ARRAY type keeps a pointer to “zend_array” structure. It’s “inherited” from zend_refcounted”, that defines the format of the first 64-bit word with reference-counter. ,array_init_size(zv, count) – creates a new empty PHP array and reserves memory for “count” elements. ,zend_hash_[str_|index_]exists[_ind]() – checks if an element with the given string or numeric key exists in the HashTable. ,Z_ARR(zv) – returns zend_array value of the zval (the type must be IS_ARRAY).

Читайте также:  Html menu with images with

Because the element of an array may be another array (and recursively deeper), we have to separate the scaling logic into a separate recursive function do_scale(). The logic for IS_LONG, IS_DOUBLE and IS_STRING is kept the same, except, that our function now reports SUCCESS or FAILURE to the caller and therefore we have to replace our RETURN_. () macros with RETVAL_. () and “return SUCCESS”.

static int do_scale(zval *return_value, zval *x, zend_long factor) < if (Z_TYPE_P(x) == IS_LONG) < RETVAL_LONG(Z_LVAL_P(x) * factor); >else if (Z_TYPE_P(x) == IS_DOUBLE) < RETVAL_DOUBLE(Z_DVAL_P(x) * factor); >else if (Z_TYPE_P(x) == IS_STRING) < zend_string *ret = zend_string_safe_alloc(Z_STRLEN_P(x), factor, 0, 0); char *p = ZSTR_VAL(ret); while (factor-- >0) < memcpy(p, Z_STRVAL_P(x), Z_STRLEN_P(x)); p += Z_STRLEN_P(x); >*p = ‘\000’; RETVAL_STR(ret); > else if (Z_TYPE_P(x) == IS_ARRAY) < zend_array *ret = zend_new_array(zend_array_count(Z_ARR_P(x))); zend_ulong idx; zend_string *key; zval *val, tmp; ZEND_HASH_FOREACH_KEY_VAL(Z_ARR_P(x), idx, key, val) < if (do_scale(&tmp, val, factor) != SUCCESS) < return FAILURE; >if (key) < zend_hash_add(ret, key, &tmp); >else < zend_hash_index_add(ret, idx, &tmp); >> ZEND_HASH_FOREACH_END(); RETVAL_ARR(ret); > else < php_error_docref(NULL, E_WARNING, “unexpected argument type”); return FAILURE; >return SUCCESS; > PHP_FUNCTION(test_scale) < zval *x; zend_long factor = TEST_G(scale); // default value ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_ZVAL(x) Z_PARAM_OPTIONAL Z_PARAM_LONG(factor) ZEND_PARSE_PARAMETERS_END(); do_scale(return_value, x, factor); >

Let’s test new functionality.

$ php -r ‘var_dump(test_scale([2, 2.0, “x” => [“2”]], 3));’ array(3) < [0]=>int(6) [1]=> float(6) [“x”]=> array(1) < [0]=>string(3) “222” > >

Answer by Lucian Nash

Example: Here is an example function call with a stack drawing showing how different types are passed. ,See struct.c for more examples. Exercise: implement and test two functions in this file: printStudent and initStudent. , and what does this mean with respect to the value of each argument after the call? ,Use *var_name to dereference the pointer to access the value in the location that it points to.

int *ptr; // stores the memory address of an int (ptr "points to" an int) char *cptr; // stores the memory address of a char (cptr "points to" a char) 

Answer by Benjamin Lindsey

Since 5.2 foreach (reliably) advances the array pointer before the loop body starts. See also the FE_RESET opcode.,0 changes to z30, php continues loop the arrays, then z30 contains ‘3’, and 3 changes to z33. Because of that returns ‘z’ + ‘z33’ + ‘0’ = zz330.,Of course! You can get even whackier results when you start using references or nest multiple foreach loops on the same variable.,Use Iterators or don’t rely on getting a consistent value from referencing the array variable during a foreach operation.

Читайте также:  Java parse string to words

I’ve the following function and using str_replace gives an unexpected result

function repo($text) < $search = array("0","1","2","3","4","5","6","7","8","9"); $replace = array("z30","z31","z32","z33","z34","z35","z36","z37","z38","z99"); $text = str_replace($search,$replace,$text); return $text; >echo repo('0'); 

Answer by Darian Roberson

If the array was declared register, the behavior of the program that attempts such conversion is undefined. ,2.2 Variable-length arrays,Variable-length arrays and the types derived from them (pointers to them, etc) are commonly known as «variably-modified types» (VM). Objects of any variably-modified type may only be declared at block scope or function prototype scope. ,If qualifiers are present, they qualify the pointer type to which the array parameter type is transformed:

float fa[11], *afp[17]; // fa is an array of 11 floats // afp is an array of 17 pointers to floats

Источник

Programming for beginners

Php maintains an internal pointer that points to one of the item in the array. By default, this pointer points to the first element in the array. Php provides functions to move the pointer in forward, reverse, to the end, to the first position.

Following table summarizes the functions.

current ( array|object $array ) : mixed

Return current element of the array. If the internal pointer points beyond the end of the elements list or the array is empty, current() returns false.

next ( array|object &$array ) : mixed

It advances the internal array pointer one place forward before returning the element value.

prev ( array|object &$array ) : mixed

it rewinds the internal array pointer one place instead of advancing it.

reset ( array|object &$array ) : mixed

rewinds array’s internal pointer to the first element and returns the value of the first array element.

Читайте также:  Java пример программы android

end ( array|object &$array ) : mixed

advances array’s internal pointer to the last element, and returns its value.

Let’s see it with an example.

array_pointers_demo.php

#!/usr/bin/php  $arr1 = array(2, 3, 5, 7, 11); echo "Elements in array are : \n"; print_r($arr1); $current_element = current($arr1); echo "\nCurrent element : $current_element\n"; echo "\nAdvancing internal pointer to next index\n"; $current_element = next($arr1); echo "\nElement returned by next function: $current_element\n"; $current_element = current($arr1); echo "Current element : $current_element\n"; echo "\nAdvancing current pointer to one step backward\n"; $current_element = prev($arr1); echo "\nElement returned by prev function : $current_element\n"; $current_element = current($arr1); echo "\nCurrent element : $current_element\n"; echo "\nMoving the internal pointer to the end\n"; $current_element = end($arr1); echo "\nElement returned by end function : $current_element\n"; $current_element = current($arr1); echo "\nCurrent element : $current_element\n"; ?> 
$./array_pointers_demo.php Elements in array are : Array ( [0] => 2 [1] => 3 [2] => 5 [3] => 7 [4] => 11 ) Current element : 2 Advancing internal pointer to next index Element returned by next function: 3 Current element : 3 Advancing current pointer to one step backward Element returned by prev function : 2 Current element : 2 Moving the internal pointer to the end Element returned by end function : 11 Current element : 11 

Using array pointers to traverse the array

Traversing in forward direction

echo «current element : $current_ele\n»;

Traversing in backward direction

echo «current element : $current_ele\n»;

Find the below working application.

array_traversal_with_pointers.php

#!/usr/bin/php  $arr1 = array(2, 3, 5, 7, 11); echo "Traversing in forward direction\n"; while($current_ele = current($arr1))< echo "current element : $current_ele\n"; next($arr1); > echo "\n\nTraversing in backward direction\n"; end($arr1); while($current_ele = current($arr1))< echo "current element : $current_ele\n"; prev($arr1); > ?> 
$./array_traversal_with_pointers.php Traversing in forward direction current element : 2 current element : 3 current element : 5 current element : 7 current element : 11 Traversing in backward direction current element : 11 current element : 7 current element : 5 current element : 3 current element : 2 

Источник

Оцените статью