php array pointer oddity
php, pointers
Solution
It's definitely by design, and though I've combed through the PHP documentation, I can find no reference to the fact that once you invalidate the pointer by means of `next`ing past the end of the array you can no longer use `prev`, the PHP source code (`zend_hash.c`) makes it clear what's going on:
ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
{
HashPosition *current = pos ? pos : &ht->pInternalPointer;
IS_CONSISTENT(ht);
if (*current) {
*current = (*current)->pListNext;
return SUCCESS;
} else
return FAILURE;
}
ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos)
{
HashPosition *current = pos ? pos : &ht->pInternalPointer;
IS_CONSISTENT(ht);
if (*current) {
*current = (*current)->pListLast;
return SUCCESS;
} else
return FAILURE;
}
As you can see, the `zend_hash_move_backwards_ex` (which, in PHP, is mapped to `prev`) tests whether or not the current pointer is valid before doing anything, and `zend_hash_move_forward_ex` will set the value to `pListNext` which is going to be `null` in case of the last element.
i.e. unlike you might expect, `next` and `prev` do not just blindly increment or decrement a C pointer then check the result to return the value or NULL, they actually check the pointer before incrementing or decrementing.
This is definitely a flaw in the documentation and certainly needs to be documented. As mentioned in another reply, you can use `end` to go to the last element after a pointer has been invalidated by looping over the list.
However, you should be able to implement the logic you want (without having to use `end()`) by cloning the pointer before each progression and then using the cloned pointer after reaching the end of the array. (but there's no really good reason to do this if you already know `prev()` is broken by design in terms of backwards navigation of an already-iterated array)
(Off-topic: I'm glad to see the respected PHP tradition of using inconsistent function names is alive and well even in the underlying C code: `zend_hash_move_forward_ex` vs `zend_hash_move_backward*s*_ex`.)
Problem
``` $a=array('a','b','c','d'); while(key($a)!==NULL){ echo key($a).'=>'.current($a).'<br/>'; next ($a); } prev($a); var_dump(current($a)); ``` Why does `var_dump` return `false` instead of `"d"` ?