Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php (bool)true-var不会在数组赋值时转换为数组,但(bool)false会转换为数组。为什么?_Php_Arrays - Fatal编程技术网

Php (bool)true-var不会在数组赋值时转换为数组,但(bool)false会转换为数组。为什么?

Php (bool)true-var不会在数组赋值时转换为数组,但(bool)false会转换为数组。为什么?,php,arrays,Php,Arrays,使用PHP。。。举个例子。这会产生一个警告(正如预期的那样),并且$myVar保持为bool(true) 但下一个示例“有效”,将“$myVar转换为一个包含单个元素“Hello”的数组 $myVar = false; $myVar[] = 'Hello'; // Converted into an array 结果: array(1) { [0]=> string(5) "Hello" } 然而bool(真)和bool(假)都是标量。那么为什么会有区别呢?PHP中的什么规则

使用PHP。。。举个例子。这会产生一个警告(正如预期的那样),并且
$myVar
保持为bool(true)

但下一个示例“有效”,将“
$myVar
转换为一个包含单个元素“Hello”的数组

$myVar = false;
$myVar[] = 'Hello';  // Converted into an array
结果:

array(1) {
  [0]=>
  string(5) "Hello"
}
然而bool(真)和bool(假)都是标量。那么为什么会有区别呢?PHP中的什么规则控制这种行为?还是“就是这样”

我最初认为这可能与类型转换规则有关,但bool(true)和bool(false)在这方面表现相同


谢谢。

PHP不是强类型语言。将数组分配给包含
false
值的变量,不需要布尔
false

在PHP封面下,它必须将
$myVar
视为具有一个计算结果为空的值,因此允许数组赋值


同样,如果您将PHP视为一种动态脚本语言,这并不完全出乎意料。

如果您想知道为什么会这样,请签出PHP,编译它,并使用gdb进行逐步调试。。。除非有人足够优秀,能够找到对此负责的代码。 然后看看代码周围的注释(如果有)。 正如下面的评论中提到的,另一种查找方法是搜索代码以查找错误消息。让我们这样做

    [greg@liche php-src-5.3]$ grep -rn --exclude-dir=".svn" "Cannot use a scalar value as an array" .
./tests/lang/bug29893.phpt:10:Warning: Cannot use a scalar value as an array in %sbug29893.php on line %d
./tests/lang/engine_assignExecutionOrder_002.phpt:12:// Warning: Cannot use a scalar value as an array in %s on line %d
./tests/lang/engine_assignExecutionOrder_002.phpt:94:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/zend_execute.c:1015:                             zend_error(E_WARNING, "Cannot use a scalar value as an array");
./Zend/tests/indexing_001.phpt:51:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:54:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:57:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:77:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:96:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:99:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:102:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:119:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:137:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:140:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:143:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:160:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:179:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:182:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:185:Warning: Cannot use a scalar value as an array in %s on line %d
./Zend/tests/indexing_001.phpt:202:Warning: Cannot use a scalar value as an array in %s on line %d
看起来它在zend_execute.c中,下面是我发现的:

 case IS_BOOL:
1223    if (type != BP_VAR_UNSET && Z_LVAL_P(container)==0) {
1224    goto convert_to_array;
1225    }
1226    /* break missing intentionally */
1227    
1228    default:
1229    if (type == BP_VAR_UNSET) {
1230    zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
1231    AI_SET_PTR(result, &EG(uninitialized_zval));
1232    PZVAL_LOCK(&EG(uninitialized_zval));
1233    } else {
1234    zend_error(E_WARNING, "Cannot use a scalar value as an array");
1235    result->var.ptr_ptr = &EG(error_zval_ptr);
1236    PZVAL_LOCK(EG(error_zval_ptr));
1237    }
1238    break; 

我认为ZLVAL\u p(container)=0条件是造成这种差异的原因。。。lval表示左值,即正在分配的值。。。我认为它的计算结果为0。

所以,尽管我不知道PHP为什么会这样做,但我看了一些Zend代码,至少可以告诉您在哪里可以找到PHP是如何做到这一点的

所以,重要的代码在

那么,让我们来介绍一下上述情况:

如果它
是_ARRAY
-一切都很明显

如果它
是\u对象
抛出错误,除非它有
数组访问

如果
是\u STRING
抛出错误,除非字符串长度为零

如果
为空
则创建一个新数组

如果它
为布尔值,则抛出一个错误,除非它为false

否则,抛出一个错误

因此,这证实了您和我的测试:

如果对象、非空字符串、
true
和其他标量(即long和double)出现错误。
如果是数组、空字符串、
null
false
,则无错误。因此,基本上它对大多数(但不是所有)“falsy”值进行自动强制转换。

虽然PHP是松散类型,但类型仍然具有一定的重要性,因此===或!==比如说

如果Nikic被重置为零,它会出错的原因是它现在实际上是一个整数,而不是布尔值

为了演示,您可以执行以下操作,并通过强制转换获得相同的错误

$a = (int) false;
$a[] = 'goat'; #throws warning, thinks it's a 0

$a = (bool) 0;
$a[] = 'goat'; #works, thinks it's a false

然而,我知道这只是一个迂腐的例子!(bool)true的计算结果仍然是1。

你到底为什么要做这样的事?:]这是一个非常简单的例子。函数在允许的错误状态下返回数组或(bool)false。然后使用
$myVar[$key]
将元素添加到此数组中。在(bool)false的情况下,将创建一个新数组-非常好。然后有一天,函数做了一些奇怪的事情,返回int(1),脚本失败了。这让我想知道为什么这个脚本一开始就用(bool)false!这不可能是全部真相。正如我在回答中所说,
0
即使
empty
也会抛出一个错误。虽然PHP不是强类型的,但它是一个布尔假值(==false)。是的,正如nikic所说,当var计算为空时也不一定如此。@nikic,这肯定不是全部正确的。但很明显,它没有像w3d所提到的那样进行严格的平等性检查。如果你发现了全部真相,那么你就回答了自己的问题;)我已经在查看Zend代码,但找不到导致这种奇怪现象的文件。找到第612行
convert\u scalar\u to \u array
。这可能是函数,但它对我也没有帮助。至少它没有向我解释任何事情。如果你对一个数组输入(bool)true或(bool)false,你会得到基本相同的结果。。。元素值为(bool)true或(bool)false的单个元素数组。我们不知道是否有强制转换的尝试。我们正在查找的代码使用了运算符“[”。在checkouted本地副本中搜索错误消息将是一个很好的方法。@gregwire yes true。事实上,该值已被覆盖/替换(或“转换”),根本没有强制转换。是的,感谢您的分解。因此,您的初始响应似乎是,“我认为这是因为一个是
true
,另一个是
false
:D这就是PHP!“,基本上在按钮上!:)其实一点也不奇怪。将空数组转换为
bool
会产生
false
,而将非空数组转换为
bool
则会产生
true
。这是一个愚蠢的语法糖,可以让你通过一个简单的
if($array)来测试数组是否为空。”
。向后看,
false
应该在逻辑上转换为空数组。但是,没有明智的方法将
true
转换为填充数组,因此会抛出错误。@meagar:当然可以将true转换为填充数组:php>var_dump((数组)true);数组(1){[0]=>bool(true)}@w3d:随着时间的推移,我完全忘记了这一点。但现在再看一遍,我认为这种行为是有意义的。PHP的一个特性是数组不需要显式初始化,也就是说,您可以编写
$array[]='x'
即使尚未定义
$array
。上述行为与此相匹配,允许推送到
null
值(
$a = (int) false;
$a[] = 'goat'; #throws warning, thinks it's a 0

$a = (bool) 0;
$a[] = 'goat'; #works, thinks it's a false