Я пробовал этот код
$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 не является отрицательным?
Я пробовал этот код
$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 не является отрицательным?
Используйте источник, Luke
Как обычно, ответ лежит в источнике. 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, но переменная определенно не обновляется.
Это не ошибка (tm)
Вы можете быть удивлены, узнав, что это поведение, в том числе и для логических значений, на самом деле задокументировано:
Примечание. Операторы 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 вообще и идет прямо в FAILURE:
default:
return FAILURE;
Как уже упоминалось, это документально.
Примечание. Операторы increment/decment не влияют на логические значения. Уменьшение значений
NULLтакже не влияет, но приращение их приводит к1.