30 votes

Pourquoi la décrémentation de NULL n'est pas négative dans ce tableau ?

J'ai essayé ce code

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

Résultat :

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

Pourquoi la valeur de l'indice 2 et 3 n'est pas négative ?

22voto

fvu Points 21471

Bizarre, mais documenté sur la page de documentation php sur les opérateurs d'incrémentation/décrémentation :

Remarque : les opérateurs d'incrémentation/décrémentation n'affectent pas les valeurs booléennes. Décrémenter les valeurs NULL n'a aucun effet non plus, mais les incrémenter donne 1.

15voto

Jack Points 88446

Utilise la source, Luke

Comme toujours, la réponse se trouve dans la source. PHP utilise les deux fonctions suivantes en interne pour effectuer les opérations d'incrémentation et de décrémentation :

ZEND_API int increment_function(zval *op1)

ZEND_API int decrement_function(zval *op1)

Ces opérations modifient le op1 en fonction de son type ( NULL est un type) ; à l'intérieur increment_function() vous pouvez voir la branche suivante dans le code :

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

Le code ci-dessus change le type de op1 en un nombre et fixe sa valeur à 1 .

Inversement, decrement_function() n'offre pas une telle branche et donc le action par défaut sera effectuée :

default:
    return FAILURE;

L'exécution de ce code ne produira pas d'échec observable, car les valeurs de retour sont absorbées par la Zend VM, mais la variable n'est pas non plus mise à jour.

Ce n'est pas un bug(tm)

Vous serez peut-être surpris d'apprendre que ce comportement, y compris celui des valeurs booléennes, est en réalité documenté :

Note : Les opérateurs d'incrémentation/décrémentation n'affectent pas les valeurs booléennes. Décrémenter NULL n'a pas d'effet non plus, mais les incrémenter a pour effet de 1 .

En ce qui concerne les booléens :

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

En ce qui concerne les cordes :

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

3voto

Rainulf Points 191

Étrange. Je ne sais pas ce qui les a poussés à faire ça mais en regardant les code source vous verrez que s'il s'agit d'un NULL, il est mis à 1 (et non incrémenté).

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

El décrémenter ne traite pas du tout les NULL et va directement à FAILURE :

default:
    return FAILURE;

Comme d'autres l'ont mentionné, c'est documenté .

Note : Les opérateurs d'incrémentation/décrémentation n'affectent pas les valeurs booléennes. Décrémenter NULL n'a pas d'effet non plus, mais les incrémenter a pour effet de 1 .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X