Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

truc de fou... bug de la mort

6 réponses
Avatar
Etienne SOBOLE
voulez-vous tester ce script et me dire ce que ca donne chez vous.

<?
hop(0);

function hop($v = 'TEST')
{
if ($v == 'TEST')
echo 'etrange';
}
?>

chez moi ca ecrit 'etrange', ce qui est etrange...
a noter:

1 - si on remplace hop(0); par hop(1); ca n'ecrit plus 'etrange'
2 - si on remplace le == (2 egal) par === (3 egal) ca n'ecrit plus 'etrange'

Alors je veux bien qui soit spécifié je sais pas ou qu'une variable puisse à
la fois valoir un entier (0) et une chaine ('TEST'), mais bon ca ressemble
quand meme gravement à une grosse coquille....

PS : je suis sous PHP 4.3.3 si quelqu'un veut tester sous un PHP plus recent
(genre le 5, ca serait sympa ;)

Etienne

6 réponses

Avatar
Paul Delannoy
Etienne SOBOLE a écrit:
voulez-vous tester ce script et me dire ce que ca donne chez vous.

<?
hop(0);

function hop($v = 'TEST')
{
if ($v == 'TEST')
echo 'etrange';
}
?>


Explications : il y a == et === parce que PHP essaie de comparer sans
comparer les types (==) Dans ton cas 'TEST' est une chaine non affectée,
donc sa valeur est nulle, le test marche avec 0 !! avec 1 il ne marche
pas ...
Avec === le type sera vérifié aussi et donc cela ira bien.
Lecture recommandée de : http://www.php.net/operators.comparison
J'eqça

Avatar
ED
Etienne SOBOLE wrote:
voulez-vous tester ce script et me dire ce que ca donne chez vous.


même chose chez moi (PHP 5 RC3) mais c'est normal

2 - si on remplace le == (2 egal) par === (3 egal) ca n'ecrit plus 'etrange'


C'est ça qui aurait du te mettre la puce à l'oreille.

Tu transmet 0 à ta fonction. La valeur reçuz dans $v est donc bien 0 et
pas la valeur par défaut 'TEST'. Le problème est plus loin, au niveau de
la comparaison.

Tu compares un nombre à une chaîne de caractère. Les deux types étant
différents PHP doit forcément en convertir un des deux pour pouvoir
comparer les valeurs. Lors d'une comparaison texte/nombre PHP choisit de
convertir le texte en nombre. 'TEST' converti en nombre entier ça donne
bien zéro, et la comparaison se fait avec ce chiffre là. Pour faire
simple 0=='TEST' est strictement équivalent à 0==intval('TEST') qui lui
même est strictement équivalent à 0==0.

Si tu veux faire en sorte que tes opérandes ne soient pas
automatiquement converties dans un autre type il te faut employer "===".
Dans ce cas PHP on fait une égalité de valeur ET de type (contrairement
à "==" qui ne compare que les valeurs). Les types étant différents le
test renverrait faux (ce que tu as constaté).

1 - si on remplace hop(0); par hop(1); ca n'ecrit plus 'etrange'


Quand tu fais ça la comparaison devient : 1==intval('TEST') ce qui donne
1==0. Le test échoue bel et bien donc rien n'est affiché.


Alors je veux bien qui soit spécifié je sais pas ou qu'une variable puisse à
la fois valoir un entier (0) et une chaine ('TEST'), mais bon ca ressemble
quand meme gravement à une grosse coquille....


PHP a un typage faible. Pour simplifier l'utilisation des variables les
développeurs considèrent que l'utilisateur ne doit pas avoir à chercher
si une variable est une chaîne de caractères ou un nombre. La
conséquence c'est qu'à chaque fois que tu joues avec deux types de
données différentes il y a un transtypage. Et certains transtypages sont
parfois assez étranges quand on n'y fait pas attention.
Globalement le meilleur moyen de faire des erreurs c'est justement de
comparer des choux (texte) et des carottes (nombres). Dans ces cas là
essaies d'utiliser le plus possible les opérateurs !== et ===.


--
Eric Daspet
*
Vous cherchez une doc sur PHP 5 ? *PHP 5 avancé*, aux éditions Eyrolles
http://www.eyrolles.com/Informatique/Livre/9782212113235/-PHP-5-avance

Avatar
Benoit F
J'utilise le dernière version téléchargeable sur le site de php :
php5RC2 et j'obtiens effectivement la même chose.

le test "0 == 'TEST' " implique une conversion en entier de 'TEST' et
donc 'TEST' est converti en un entier egal à 0 et donc :

hop(): etrange ($v=TEST donc c'est normal)
hop(0): etrange ( $v=0 et donc en convertissant 'TEST' en 0 c'est normal)
hop(true): etrange( $v=true et comme 'TEST' n'est pas false alors c'est
normal)

C'est assez étrange comme truc effectivement, mais ça s'explique

--
Benoit F.
Avatar
Antoine Dinimant
En fait, c'est parfaitement normal...

essaie :

hop(0);

function hop($v = 'TEST')
{
echo "|$v|<br>" ;
echo gettype($v) . "<br>" ;
if ($v == 'toto')
echo 'etrange<BR>';
}

résultat :
$v vaut vraiment 0
c'est un entier et non une chaîne
($v == 'toto') est vrai, donc ça n'a pas de rapport avec ta définition
par défaut

maintenant, si on essaie la même chose avec hop('0'),
que constate-t-on ?

$v vaut bien '0'
c'est une chaîne
($v == 'toto') est faux

en fait quand tu compares une chaîne avec un nombre, tu fais une
conversion implicite de ta chaîne en nombre. Elle vaut alors 0 et donc
ton $v == 'TEST' est vrai. Avec === par contre, tu ne risques rien.

C'est là où on voit que la souplesse de PHP recèle des surprises !

Antoun
Avatar
Etienne SOBOLE
"ED" a écrit dans le message de news:
40d45108$0$298$

2 - si on remplace le == (2 egal) par === (3 egal) ca n'ecrit plus
'etrange'


C'est ça qui aurait du te mettre la puce à l'oreille.


En effet !

Tu compares un nombre à une chaîne de caractère. Les deux types étant
différents PHP doit forcément en convertir un des deux pour pouvoir
comparer les valeurs. Lors d'une comparaison texte/nombre PHP choisit de
convertir le texte en nombre. 'TEST' converti en nombre entier ça donne
bien zéro, et la comparaison se fait avec ce chiffre là. Pour faire
simple 0=='TEST' est strictement équivalent à 0==intval('TEST') qui lui
même est strictement équivalent à 0==0.


Ouaip !!! C'est vrai qu'avec un minimum de réflexion, j'aurai pu faire vous
faire grâce de ma contribution... :)
Le truc, c'est que comme habituellement je cast moi meme les variables avant
de les tester, le bug lorsqu'il est aparu m'a semblé byzarre, mais c'est
vrai que c'est pô un bug.


Bon je répond ici, mais ca vaut pour tout le monde ;)
Merci
Etienne


Avatar
John Gallet
Bonjour,

function hop($v = 'TEST')
{
if ($v == 'TEST')
echo 'etrange';
}
?>
chez moi ca ecrit 'etrange', ce qui est etrange...
a noter:
1 - si on remplace hop(0); par hop(1); ca n'ecrit plus 'etrange'
2 - si on remplace le == (2 egal) par === (3 egal) ca n'ecrit plus 'etrange'


Malheureusement, c'est normal. Pour une raison incompréhensible, le test
du typage de variable prime sur le contenu. C'est une **connerie** qui
est apparue en php4 (rendant donc incompatible certains scripts php3 où
ton test aurait été "$v est zéro c'est à dire la même chose que chaîne
vide "" et donc "" !='TEST' donc test=>FALSE).

Ce comportement est illogique : quand on a du non nul on compare le
contenu, quand on a du nul on compare le typage. C'est stupide et source
de confusions.

Bref, faudrait se décider : ou php est faiblement typé cas dans lequel
c'est le comportement de php3 qui est logique, ou il est fortement typé
mais alors il l'est partout, pas un coup l'un un coup l'autre. C'est
encore plus pénible pour ceux qui ont appris php en version 3 (et la
maintenance des scripts).

Un excellent cas d'application de la formule habituelle : "it's not a
bug, it's a feature."

a++
JG