Jan 18

php把字符串当作数组处理时的一段逻辑 不指定

felix021 @ 2010-1-18 17:53 [IT » 程序设计] 评论(1) , 引用(0) , 阅读(7370) | Via 本站原创 | |
今天windy在群里提出一个问题: 为什么下面这段代码输出了why?
$arr = 'windy';
if (isset($arr['why'])) {
  echo 'why';
}

因为已经有结果了,反推过去,很容易就会想到,php把字符串当作数组来用了。再通过
echo $arr['why'];
验证一下,发现输出的是w, 也就是$arr{0}的值,可以大致得出一个结论:当把字符串当作数组使用的时候,会自动把索引转换成整形,然后再当作字符串的偏移量读取返回。

由于此结论仅为猜测,想进一步证实,但是对php代码不熟悉,翻了zend_hash.c等文件都没找到北,因此请教了雪候鸟大人,得知真正的处理代码位于
@ php-5.2.8/Zend/zend_execute.c +1026
static void zend_fetch_dimension_address(temp_variable *result, zval **container_ptr, zval *dim, int dim_is_tmp_var, int type TSRMLS_DC)
这个函数的作用是:将container_ptr所指向的container这个容器中,索引为dim的值取出放在result所指定的内存中去。

具体实现的代码是
1063     switch (Z_TYPE_P(container)) {
1064         zval **retval;
....
1099         case IS_STRING: { //如果这个容器是string
1100                 zval tmp;
1101
1102                 if (dim == NULL) {
1103                     zend_error_noreturn(E_ERROR, "[] operator not supported for strings");
1104                 }
1105
1106                 if (Z_TYPE_P(dim) != IS_LONG) {  //如果偏移量的类型不是LONG
1107                     switch(Z_TYPE_P(dim)) {
1108                         /* case IS_LONG: */  
1109                         case IS_STRING:  
1110                         case IS_DOUBLE:
1111                         case IS_NULL:
1112                         case IS_BOOL:
1113                             /* do nothing */   //允许STRING, DOUBLE, NULL, BOOL四种类型
1114                             break;
1115                         default: //其他类型都报错
1116                             zend_error(E_WARNING, "Illegal offset type");
1117                             break;
1118                     }
1119
1120                     tmp = *dim;
1121                     zval_copy_ctor(&tmp);
1122                     convert_to_long(&tmp);
1123                     dim = &tmp;  //将原来的dim转换成LONG
1124                 }      
1125                 switch (type) {
1126                     case BP_VAR_R:
1127                     case BP_VAR_IS:
1128                     case BP_VAR_UNSET:
1129                         /* do nothing... */
1130                         break;
1131                     default:
1132                         SEPARATE_ZVAL_IF_NOT_REF(container_ptr);
1133                         break;
1134                 }
1135                 if (result) { //存放结果
1136                     container = *container_ptr;
1137                     result->str_offset.str = container;
1138                     PZVAL_LOCK(container);
1139                     result->str_offset.offset = Z_LVAL_P(dim);
1140                     result->var.ptr_ptr = NULL;
1141                     if (type == BP_VAR_R || type == BP_VAR_IS) {
1142                         AI_USE_PTR(result->var);
1143                     }
1144                 }
1145                 return;
1146             }
1147             break;

简单写了一点注释,只能大致看懂逻辑,其他边边角角的,暂时就没时间看了:'(



欢迎扫码关注:




转载请注明出自 ,如是转载文则注明原出处,谢谢:)
RSS订阅地址: https://www.felix021.com/blog/feed.php
sandy
2010-1-19 11:14
所以说任何框架都不可能达到完全的封装。。。要想成为高手还得去了解其内部的东西。。而这样又引入过多的相关性。。复杂性又随之而来。。咳咳
felix021 回复于 2010-1-19 11:19
是啊  引入更高的复杂性来解决现有复杂性带来的问题,往往会导致恶性循环。
分页: 1/1 第一页 1 最后页
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   *非必须
网址   电邮   [注册]