5
$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"

4

2 回答 2

4

这绝对是设计使然,尽管我已经梳理了 PHP 文档,但我找不到任何关于这样一个事实的参考,即一旦通过next数组末尾的 ing 使指针无效,您将无法再使用prevPHP 源代码( 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并将设置最后一个元素的pListNextnull

即不像您可能期望的那样,next并且prev不要只是盲目地增加或减少 C 指针然后检查结果以返回值或 NULL,它们实际上会在增加或减少之前检查指针。

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

end()但是,您应该能够通过在每个进程之前克隆指针,然后在到达数组末尾后使用克隆的指针来实现您想要的逻辑(无需使用)。(但如果您已经知道prev()在已经迭代的数组的向后导航方面被设计破坏,那么没有真正好的理由这样做)

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

于 2012-05-22T07:09:56.210 回答
0
$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

于 2012-05-22T07:01:07.557 回答