Friday, January 22, 2010

PHP: Array Pointer in Undefined State

Array pointer in PHP may become "undefined" and that is when you try to move it after the last of before the first element. But what is more surprising - copying an array remaining in that state... resets the pointer.

First let's create a messy array and see how it dumps:

$a = array (5 => 'key 5', 'key after 5', 3 => 'key 3', 'a' => 'key a', 1 => 'key 1', 0 => 'key 0', 'key after 0',);
var_dump($a);

The result (as expected):

array(7) {
  [5]=>
  string(5) "key 5"
  [6]=>
  string(11) "key after 5"
  [3]=>
  string(5) "key 3"
  ["a"]=>
  string(5) "key a"
  [1]=>
  string(5) "key 1"
  [0]=>
  string(5) "key 0"
  [7]=>
  string(11) "key after 0"
}

When Array Pointer Becomes Undefined

Let's try and go beyond the last element in the array:

// move the pointer to the last element
end($a);

// move the pointer one element further
next($a);

// ... and see where we are
var_dump(key($a), current($a));

// try to go back
prev($a);

// ... and see where we are
var_dump(key($a), current($a));

The above code will produce the following result:

NULL
bool(false)

NULL
bool(false)

Which simply means that the array pointer becomes "undefined" if moved after last element. In fact the pointer is not "after" the last element because you cannot move it back with

prev()
function. It simply remains in undefined state.

Copying Array Resets The Pointer

When you copy an array, the array pointer is copied as well and it points to the same element as in the original. But what happens when the pointer is undefined? Will the copy inherit that as well? Let's consider the code:

// copy the array
$b = $a;

// check state of the original
print ('original: key() and current()' . PHP_EOL);
var_dump(key($a), current($a));

// check state of the copy
print ('copy: key() and current()' . PHP_EOL);
var_dump(key($b), current($b));

And the result:

original: key() and current()
int(5)
string(5) "key 5"

copy: key() and current()
NULL
bool(false)

Just as anticipated, the copy has its pointer in undefined state. But what happened to the original? Apparently copying the array worked like

reset()
and moved the pointer to the first element! Needless to say, copying the array preserves the pointer's value if it's defined:

// move the pointer to the last element
end($a);

// move the pointer to one element before last
prev($a);

// see where we are
print ('key() and current()' . PHP_EOL);
var_dump(key($a), current($a));

// copy the array
$b = $a;

// check state of the original
print ('original: key() and current()' . PHP_EOL);
var_dump(key($a), current($a));

// check state of the copy
print ('copy: key() and current()' . PHP_EOL);
var_dump(key($b), current($b));

And the output:

key() and current()
int(0)
string(5) "key 0"

original: key() and current()
int(0)
string(5) "key 0"

copy: key() and current()
int(0)
string(5) "key 0"

Moving Array Pointer Before First Element

All the above applies to the situation when you move the pointer "before" the first element. But don't take my word for it - try it out.

1 comment:

  1. Just squished an old bug in a PHP app where the pointer was automatically getting reset... Turns out it was because the copied array had a pointer that was out of bounds! Your blog helped me pinpoint the issue, so thanks!

    ReplyDelete