为了能在遍历时同时接收索引的值,就像PHP语言中这样的功能:
1
2
3
4
5
6
|
<?php
foreach
(
$arr
as
$key
=>
$val
)
{
echo
"The value of $key is: $val\n"
;
}
?>
|
为了配合zend_hash_apply_with_arguments()函数,我们需要使其接受索引作为一个参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
int
php_sample_print_zval_and_key(zval **val,
int
num_args,
va_list
args,zend_hash_key *hash_key)
{
//重新copy一个zval,防止破坏原数据
zval tmpcopy = **val;
/* tsrm_ls is needed by output functions */
TSRMLS_FETCH();
zval_copy_ctor(&tmpcopy);
INIT_PZVAL(&tmpcopy);
//转换为字符串
convert_to_string(&tmpcopy);
//执行输出
php_printf(
"The value of "
);
if (hash_key->nKeyLength)
{
//如果是字符串类型的key
PHPWRITE(hash_key->arKey, hash_key->nKeyLength);
}
else
{
//如果是数字类型的key
php_printf( "%ld" , hash_key->h);
}
php_printf(
" is: "
);
PHPWRITE(Z_STRVAL(tmpcopy), Z_STRLEN(tmpcopy));
php_printf(
"\n"
);
//毁尸灭迹
zval_dtor(&tmpcopy);
/* continue; */
return
ZEND_HASH_APPLY_KEEP;
}
|
执行遍历:
1
|
zend_hash_apply_with_arguments(arrht,php_sample_print_zval_and_key, 0);
|
这个函数通过C语言中的可变参数特性来接收参数。This particular example required no arguments to be passed; for information on extracting variable argument lists from va_list args, see the POSIX documentation pages for va_start(), va_arg(), and va_end().
当我们检查这个hash_key是字符串类型还是数字类型时,是通过nKeyLength属性来检测的,而不是arKey属性。这是因为内核有时候会留在arKey属性里些脏数据,但nKeyLength属性是安全的,可以安全的使用。甚至对于空字符串索引,它也照样能处理。比如:$foo[''] ="Bar";索引的值是NULL字符,但它的长度却是包括最后这个NULL字符的,所以为1。