Почему декремент NULL не отрицателен в этом массиве?

Я пробовал этот код

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

Результат:

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

Почему значение индекса 2 и 3 не является отрицательным?

Related of "Почему декремент NULL не отрицателен в этом массиве?"

Используйте источник, Люк

Как обычно, ответ лежит в источнике. PHP выполняет следующие внутренние функции для выполнения операций инкремента и декремента:

ZEND_API int increment_function(zval *op1)

ZEND_API int decrement_function(zval *op1)

Эти операции изменяют аргумент op1 на основе его типа ( NULL – это тип); внутри increment_function() вы можете увидеть следующую ветку в коде :

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

Вышеприведенный код меняет тип op1 на число и устанавливает его значение в 1 .

Напротив, decrement_function() не имеет такой ветви и поэтому будет выполняться действие по умолчанию :

 default: return FAILURE; 

Выполнение этого кода фактически не приведет к заметному сбою, поскольку возвращаемые значения будут поглощены Zend VM, но переменная определенно не обновляется.

Это не ошибка ™

Вы можете быть удивлены, узнав, что это поведение, в том числе и для логических значений, действительно документировано :

Примечание. Операторы increment / decment не влияют на логические значения. Уменьшение значений NULL также не влияет, но приращение их приводит к 1 .

Что касается булевых:

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

Что касается строк:

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

Странно, но задокументировано на странице «Приращения / сокращения» php doc:

Примечание. Операторы increment / decment не влияют на логические значения. Уменьшение значений NULL также не влияет, но приращение их приводит к 1.

Странный. Я не знаю их решающего фактора для этого, но, глядя на исходный код , вы увидите, что если он имеет дело с NULL, он устанавливает его в 1 (не приращение).

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

Функция декремента вообще не имеет отношения к NULL и идет прямо к ошибке:

 default: return FAILURE; 

Как уже упоминалось, это документировано .

Примечание. Операторы increment / decment не влияют на логические значения. Уменьшение значений NULL также не влияет, но приращение их приводит к 1 .