Foreach pointer problems

Source: Internet
Author: User
In PHP, the foreach syntax structure provides a simple way to traverse arrays. Foreach can only be applied to arrays and objects. if you try to apply it to variables of other data types or uninitialized variables, an error will occur. During each foreach loop, the value of the current unit is assigned to $ value and the pointer inside the array moves forward (so the next unit will be obtained in the next loop ).

In PHP, the foreach syntax structure provides a simple way to traverse arrays. Foreach can only be applied to arrays and objects. if you try to apply it to variables of other data types or uninitialized variables, an error will occur. During each foreach loop, the value of the current unit is assigned to $ value and the pointer inside the array moves forward (so the next unit will be obtained in the next loop ).

But the manual reminds us:

Note: When foreach starts to execute, the pointer inside the array automatically points to the first unit. This means that you do not need to call reset () before the foreach loop (). Modifying the foreach dependency on its internal array pointer in a loop may cause unexpected behavior.

What we want to talk about here is the unexpected situation caused by foreach. Sample Code 1:

  &$row) { echo key($arr), '=>', current($arr), "\r\n"; }

What will be output?

For example, code 2?

  $row) { echo key($arr), '=>', current($arr), "\r\n"; }

What will be output?

Code 1 outputs variables in sequence, but the first element does not appear in the output result.

Code 2 outputs only the second element of the array.

Why?

View Code 2 in the VLD extension,

number of ops:  22compiled vars:  !0 = $arr, !1 = $key, !2 = $rowline     # *  op                           fetch          ext  return  operands---------------------------------------------------------------------------------   2     0  >   INIT_ARRAY                                       ~0      1         1      ADD_ARRAY_ELEMENT                                ~0      2         2      ADD_ARRAY_ELEMENT                                ~0      3         3      ADD_ARRAY_ELEMENT                                ~0      4         4      ADD_ARRAY_ELEMENT                                ~0      5         5      ASSIGN                                                   !0, ~0   4     6    > FE_RESET                                         $2      !0, ->20         7  > > FE_FETCH                                         $3      $2, ->20         8  >   ZEND_OP_DATA                                     ~5               9      ASSIGN                                                   !2, $3        10      ASSIGN                                                   !1, ~5   5    11      SEND_REF                                                 !0        12      DO_FCALL                                      1  $7      'key'        13      ECHO                                                     $7        14      ECHO                                                     '%3D%3E'        15      SEND_REF                                                 !0        16      DO_FCALL                                      1  $8      'current'        17      ECHO                                                     $8        18      ECHO                                                     '%0D%0A'   6    19    > JMP                                                      ->7        20  >   SWITCH_FREE                                              $2   8    21    > RETURN                                                   1

From the above VLD extension output results combined with PHP source code, we can know that before foreach traversal, the PHP kernel will first have a FE_RESET operation to reset the internal pointer of the array, that is, pInternalPointer, then, each FE_FETCH points pInternalPointer to the next element of the array to achieve sequential traversal.
The results of each FE_FETCH are stored by a global intermediate variable for the next element to be acquired.

Three problems can be raised from the two examples:

1. Why does the execution of key or current in the foreach loop body display the second element (non-reference )?
Take the key function as an example. when we execute a function call, the intermediate code SEND_REF will be executed. this intermediate code will copy the variables that have not been referenced and set them as references. When the loop body is entered, the PHP kernel has undergone a fetch operation, which is equivalent to executing a next operation. the current element points to the second element. Therefore, when we execute the key function in the foreach loop body, the array variable called in the key is an array copy for PHP to execute a fetch operation. at this time, the internal pointer of foreach points to the second element.

2. Why does the loop process remain unchanged when performing end and other operations in foreach?
In the traversal code, the array pointer will not change through the end, next and other operations on the array, because when the PHP kernel performs the FETCH operation, the internal pointer of the current operation array is stored through the intermediate variable. each time an element is traversed, the pointer position previously stored is obtained first, and the next element is retrieved before the pointer position is restored.

3. Why is the output result different when $ row is referenced or not referenced?
If it is a reference, when the PHP kernel reset the array, it will directly split the array, generate a copy of the array, and set it as a reference.
If it is not a reference, when the PHP kernel is in the reset array, when the reference count of the array is greater than 1, and there is no reference, the array will be copied for foreach. Otherwise, the original array will be used, add the reference count to 1.

Because of the different references, the results are different when passing parameters to the function in the loop body, resulting in different internal pointer changes in the foreach array. If the reference count is not referenced and the reference count is greater than 1, it is two different arrays, which are different in RESET.

Address: foreach pointer problem article Source: PHP source code reading, PHP design mode, PHP study notes, project management-fat space

For reprinting, please indicate the original source and author in the form of a link, and refuse to plagiarize those who do not respect copyrights!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.