Home » Php » php – Why decremented of NULL not negative in this array?

php – Why decremented of NULL not negative in this array?

Posted by: admin April 23, 2020 Leave a comment

Questions:

I have tried this code

$a = array_fill(0, 4, NULL);
$a[0]++;
++$a[1];
$a[2]--;
--$a[3];
var_dump($a);

Result:

array(4) {
    [0]=> int(1)
    [1]=> int(1)
    [2]=> NULL
    [3]=> NULL
}

Why value of 2 and 3 index is not negative?

How to&Answers:

Use the source, Luke

As usual, the answer lies in the source. PHP uses the following two functions internally to perform the increment and decrement operations:

ZEND_API int increment_function(zval *op1)

ZEND_API int decrement_function(zval *op1)

These operations modify the op1 argument based on its type (NULL is a type); inside increment_function() you can see the following branch in the code:

case IS_NULL:
    ZVAL_LONG(op1, 1);
    break;

The above code changes the type of op1 into a number and sets its value to 1.

Conversely, decrement_function() offers no such branch and therefore the default action will be performed:

default:
    return FAILURE;

Running this code won’t actually yield any observable failure, because the return values are absorbed in the Zend VM, but the variable definitely isn’t updated either.

It’s not a bug(tm)

You may be surprised to know that this behaviour, including that for boolean values, is actually documented:

Note: The increment/decrement operators do not affect boolean values. Decrementing NULL values has no effect too, but incrementing them results in 1.

Regarding booleans:

$a = true;
var_dump($a--); // true
$a = false;
var_dump($a++); // false

Regarding strings:

$letter = 'A';
var_dump(++$letter); // B
var_dump(--$letter); // B

Answer:

Weird, but documented on the Incrementing/Decrementing Operators php doc page:

Note: The increment/decrement operators do not affect boolean values. Decrementing NULL values has no effect too, but incrementing them results in 1.

Answer:

Strange. I don’t know their deciding factor to this but looking at the source code, you’ll see that if it’s dealing with a NULL, it sets it to 1 (not increment).

case IS_NULL:
    ZVAL_LONG(op1, 1);
    break;

The decrement function doesn’t deal with NULL at all and goes straight to FAILURE:

default:
    return FAILURE;

As others mentioned, it is documented.

Note: The increment/decrement operators do not affect boolean values. Decrementing NULL values has no effect too, but incrementing them results in 1.