PHP 数组指针奇特


php array pointer oddity

$a=array('a','b','c','d');
while(key($a)!==NULL){
  echo key($a).'=>'.current($a).'<br/>';
  next ($a);
}
prev($a);
var_dump(current($a));

为什么var_dump返回false而不是"d"

这绝对是设计使然,尽管我已经梳理了 PHP 文档,但我找不到以下事实的参考:一旦您通过next数组末尾使指针无效,您将无法再使用 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;
}

如您所见,zend_hash_move_backwards_ex(在 PHP 中映射到 prev (在执行任何操作之前测试当前指针是否有效,zend_hash_move_forward_ex会将值设置为 pListNext,在最后一个元素的情况下将被null

即,与您可能期望的不同,nextprev不只是盲目地增加或减少 C 指针,然后检查结果以返回值或 NULL,它们实际上在递增或递减之前检查指针。

绝对是文档中的一个缺陷,当然需要记录。如另一条回复中所述,您可以使用end在指针失效后通过循环列表转到最后一个元素。

但是,您应该能够实现所需的逻辑(不必使用 end()(,方法是在每次进行之前克隆指针,然后在到达数组末尾后使用克隆的指针。(但是,如果您已经知道在已经迭代的数组的向后导航方面设计破坏prev()那么就没有很好的理由这样做(

(题外话:我很高兴看到使用不一致函数名称的受人尊敬的PHP传统即使在底层C代码中也仍然存在:zend_hash_move_forward_ex vs zend_hash_move_backward*s*_ex

$a=array('a','b','c','d');
while(key($a)!==NULL){
  echo key($a).'=>'.current($a).'<br/>';
  next ($a);
}
prev($a);
var_dump(current($a));

在此代码中,next 返回下一个值并前进到下一个点,在循环结束时,它给出最后一个元素,但指针前进到下一个即 null。 所以你的var_dump(current($a));调谐器false

$a=array('a','b','c','d');
while(key($a)!==NULL){
  echo key($a).'=>'.current($a).'<br/>';
  next ($a);
}
//prev($a);
end(($a);
var_dump(current($a));

你会得到你想要的元素D,因为它指向最后一个元素D