5

I'm not sure this is a bug, so can anyone tell why does not php show a notice if you try to access a key which is not defined of an array that is NULL? Documentation says

Converting NULL to an array results in an empty array.

So accessing a key that is not defined must generate notice.

<?php

$a = NULL;
echo $a['1'];

$a = array();
echo $a['1'];
?>

Prints out ony

Notice: Undefined offset: 1 in /var/www/shared/1.php on line 14

Thank you for your help.


Edit: I take the liberty of adding another example script to the question

<?php
$a = NULL;
var_dump('line '.__LINE__, $a['1']);

$a = array();
var_dump('line '.__LINE__, $a['1']);

which prints

string(6) "line 3"
NULL

Notice: Undefined offset: 1 in [...]/test.php on line 6
string(6) "line 6"
NULL
9
  • 1
    You're not converting NULL to an array; you're treating it as a string when you're trying to access the character at offset 1 Commented Mar 17, 2014 at 14:12
  • 1
    @MarkBaker: That's what I thought too, but... var_dump($a['1']) => NULL. Commented Mar 17, 2014 at 14:13
  • 1
    Quoting from the manual: Characters within strings may be accessed and modified by specifying the zero-based offset of the desired character after the string using square array brackets, as in $str[42]. Commented Mar 17, 2014 at 14:14
  • 1
    It seems to me the answer is simply "well, the null is not converted to anything -- simply indexing into null always returns null no matter the index you use". Why? Because PHP. But the source is too convoluted for me to back this up with facts. Commented Mar 17, 2014 at 14:23
  • 1
    @MarkBaker: which would be the same problem: the OP would expect a PHP Notice: Uninitialized string offset: 1 in ... error in that case. Which isn't triggered either. Commented Mar 17, 2014 at 14:24

2 Answers 2

3

When you dereference a variable as an array (for reading), the virtual machine will internally call zend_fetch_dimension_address_read, which in turn loads the right value into the result variable, depending on the type of variable you're trying to dereference.

In the case of null (and int / float / bool), it will choose this branch:

case IS_NULL:
  result->var.ptr = &EG(uninitialized_zval);
  PZVAL_LOCK(&EG(uninitialized_zval));
  return;

Whereby EG(uninitialized_zval) is basically the null itself; no notices are raised when this happens. As Amal has pointed out, there's a bug report for this behaviour, but not much has been done about it for almost a year.

Documentation says "Converting NULL to an array results in an empty array."

An array dereference doesn't convert something into an array (unless you use [] or use it in a write context). The conversion that the manual speaks of is most likely an array cast:

var_dump((array)null);
// array(0) { }

Update

After digging into the system a little more, I found that this (partially) makes the following construct work:

$list = ['foo', 'bar', 'baz'];
while (list($key, $value) = each($list)) {
    echo "$key: $value\n";
}

When the end of the array is reached, each() returns false and so internally false[0] and false[1] are evaluated before the list() expression itself yields false.

Sign up to request clarification or add additional context in comments.

Comments

1

It seems this was actually reported as bug. Here's what I found in the comments section (description adjusted to match your variable names):

Your code:

$a = NULL;
echo $a['1'];

$a = array();
echo $a['1'];

Here, the variable $a is initially declared as a variable of type NULL. $a is initially declared as NULL.

In the first echo statement, the attempt to reference an index of 1 in $a is effectively ignored: the variable is not an array to begin with.

$a is then cast into an array. ($a = array();)

In the second echo statement,$a is an empty array, which PHP can enumerate against and ultimately determine that index 1 is not present.

Hence the first echo results in a NULL output, whilst the second results in PHP issuing an E_NOTICE.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.