$a=array('a','b','c','d');
while(key($a)!==NULL){
echo key($a).'=>'.current($a).'<br/>';
next ($a);
}
prev($a);
var_dump(current($a));
Run Code Online (Sandbox Code Playgroud)
为什么var_dump返回false而不是"d"?
这绝对是设计使然,尽管我已经梳理了 PHP 文档,但我找不到任何关于以下事实的参考:一旦通过 ingnext超过数组末尾的方式使指针无效prev,您将无法再使用 PHP 源代码( zend_hash.c) 清楚地表明了发生了什么:
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;
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,zend_hash_move_backwards_ex(在 PHP 中,映射到prev)在执行任何操作之前会测试当前指针是否有效,并将最后一个元素的zend_hash_move_forward_ex值设置为该值pListNext。null
即,与您可能期望的不同,next不要prev只是盲目地递增或递减 C 指针,然后检查结果以返回值或 NULL,它们实际上在递增或递减之前检查指针。
这绝对是文档中的缺陷,当然需要记录下来。正如另一个回复中提到的,您可以end通过循环列表来在指针失效后转到最后一个元素。
end()但是,您应该能够通过在每次前进之前克隆指针,然后在到达数组末尾后使用克隆的指针来实现您想要的逻辑(无需使用)。prev()(但是如果您已经知道在已经迭代的数组的向后导航方面被设计破坏了,那么就没有真正好的理由这样做)
(题外话:我很高兴看到受人尊敬的使用不一致 函数名称的 PHP 传统仍然存在,甚至在底层 C 代码中也表现得很好:zend_hash_move_forward_exvs zend_hash_move_backward*s*_ex。)