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

时间:2016-05-26 20:48:58

标签: 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"
}

即。我的零长度字符串被强制转换为数组。类似&#34;访问字符串的未定义索引&#34;例子不会产生这种铸造行为。

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

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

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

即。为了实现这一点,PHP中的C / C ++级别发生了什么。为什么我的变量变成了一个数组。

PHP 5.6,如果重要的话。

4 个答案:

答案 0 :(得分:12)

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

var distance = 100;
var angle = 4; // angle in radians

var x = Math.cos(angle) * distance;
var y = Math.sin(angle) * distance;

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

布尔值为false时会发生相同的转换。

case IS_STRING: {
                zval tmp;

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

使用测试确认:

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);

使用true时:

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

输出:

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

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

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

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

PHP 5.6版使用ZEND版本2.6.0

答案 1 :(得分:4)

我怀疑“”被视为未设置,然后被转换为数组。通常“”!= null!=未设置,但是,就此而言,php是一个小问题。

php > $a="test"; $a[0] = "yourmom"; var_dump( $a );
string(4) "yest"

php > $a=""; $a[0] = "yourmom"; var_dump( $a );
array(1) {
  [0]=>
  string(7) "yourmom"
}

php > var_dump((bool) "" == null);
bool(true)

php > var_dump((bool) $f == null);
PHP Notice:  Undefined variable: f in php shell code on line 1
PHP Stack trace:
PHP   1. {main}() php shell code:0

Notice: Undefined variable: f in php shell code on line 1

Call Stack:
  470.6157     225848   1. {main}() php shell code:0

bool(true)

答案 2 :(得分:1)

我试图找到PHP源代码中发生的情况。我对PHP内部的经验有限,而且一般来说是C,所以如果我错了,请有人纠正我。

我认为这发生在zend_fetch_dimension_address

   if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
        if (type != BP_VAR_UNSET && UNEXPECTED(Z_STRLEN_P(container) == 0)) {
            zval_ptr_dtor_nogc(container);
convert_to_array:
            ZVAL_NEW_ARR(container);
            zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
            goto fetch_from_array;
        }

如果容器是一个零长度的字符串,它会在它对它执行任何操作之前将其转换为数组。

答案 3 :(得分:0)

在空字符串上使用数组语法时将其更改为数组的原因是因为索引0未定义,并且在该点没有类型。这是一种案例研究。

<?php
$foo = "Hello"; // $foo[0] is a string "H"
echo $foo[0],"\n"; // H
$foo[0] = "same?"; // $foo[0] is still a string, "s" note that only the s is kept.
echo $foo,"\n"; // sello
echo $foo[0],"\n"; // s
$foo[1] = "b"; // $foo[1] is a string "b"
echo $foo,"\n"; // sbllo
$bar = ""; // nothing defined at position 0
$bar[0] = "t"; // array syntax creates an array with a string as the first index
var_dump($bar); // array(1) { [0] => string(1) "t" }