ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

PHP:为什么零长度字符串上的数组语法将字符串转换为数组?

2019-07-12 19:31:48  阅读:205  来源: 互联网

标签:php types casting php-internals


PHP中,您可以使用数组语法来访问字符串索引.以下程序

<?php
$foo = "Hello";
echo $foo[0],"\n";
?>

回声

H

但是,如果您访问零长度字符串的第一个字符

<?php
$bar = "";
$bar[0] = "test";
var_dump($bar);
?>

PHP将您的字符串转换为数组.上面的代码产生

array(1) {
    [0] =>
    string(4) "test"
}

即我的零长度字符串被强制转换为数组.类似的“访问字符串的未定义索引”示例不会产生此转换行为.

$bar = " ";
$bar[1] = "test";
var_dump($bar);

产生字符串t.即$bar仍然是一个字符串,并且不会转换为数组.

当语言需要推断和/或自动为你投射变量时,我会发现这些不直观的边缘情况是不可避免的,但有谁知道幕后发生了什么?

即,在PHP的C/C++级别发生了什么来实现这一目标.为什么我的变量变成了一个数组.

PHP 5.6,如果重要的话.

解决方法:

在C级别,当使用[]运算符完成赋值时,变量将转换为数组.当然,当它是一个字符串时,长度为0并且不是未设置的调用类型(例如,unset($test [0])).

case IS_STRING: {
                zval tmp;

                if (type != BP_VAR_UNSET && Z_STRLEN_P(container)==0) {
                    goto convert_to_array;
                }

https://github.com/php/php-src/blob/PHP-5.6.0/Zend/zend_execute.c#L1156

布尔值假值发生相同的转换.

case IS_BOOL:
            if (type != BP_VAR_UNSET && Z_LVAL_P(container)==0) {
                goto convert_to_array;
            }

通过使用测试确认:

<?php
$bar = false;
$bar[0] = "test";
var_dump($bar);

输出:

array(1) { [0]=> string(4) "test" }

使用true时:

<?php
$bar = true;
$bar[0] = "test";
var_dump($bar);

输出:

WARNING Cannot use a scalar value as an array on line number 3
bool(true)

https://github.com/php/php-src/blob/PHP-5.6.0/Zend/zend_execute.c#L1249

当值是bool类型且值为true时,将执行以下代码:

case IS_BOOL:
            if (type != BP_VAR_UNSET && Z_LVAL_P(container)==0) {
                goto convert_to_array;
            }
            /* break missing intentionally */

        default:
            if (type == BP_VAR_UNSET) {
                zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
                result->var.ptr_ptr = &EG(uninitialized_zval_ptr);
                PZVAL_LOCK(EG(uninitialized_zval_ptr));
            } else { // Gets here when boolean value equals true.
                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                result->var.ptr_ptr = &EG(error_zval_ptr);
                PZVAL_LOCK(EG(error_zval_ptr));
            }
            break;

PHP 5.6版使用ZEND版本2.6.0

标签:php,types,casting,php-internals
来源: https://codeday.me/bug/20190712/1443441.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有