Non, il n’y a pas de comparaisons ternaires en C !
Un jour en TP à la fac un autre étudiant me demandait pourquoi je tapais le code suivant :
if ((0 < x) && (x < 2)){
...
}
Personnellement, ça ne me parait pas choquant... Mais lui me soutenait qu'en C on peut faire beaucoup plus "joli", avec le code suivant, qui parait effectivement plus naturel :
if (0 < x < 2){
...
}
Bon, je dirais, pourquoi pas... Après tout, ça compile, donc comme il semble le penser, si ça compile, c'est que ça marche ! Mais qu'en est-il en réalité ?
En pratique, l'opérateur de comparaison '<' (ainsi que tous ses acolytes) est un opérateur binaire, qui ne prend donc que 2 opérandes. Alors comment fonctionne cette forme avec 2 opérateurs et 3 opérandes ?
Petit quiz express : qui renvoie le code suivant ?
printf("%i\n", (0 < 3 < 2));
Si vous avez répondu '0', vous avez perdu ! En effet, ça renvoie '1'. En fait, on pourrait changer le 3 par n'importe quelle valeur, on aurait toujours 1. Une fois qu'on a compris que cet opérateur est binaire, et qu'on applique donc le parenthésage par défaut défaut, on voit clairement à quoi correspond ce code :
(0 < 3) < 2
Si ce code compile, c'est uniquement parce qu'on peut effectivement l'évaluer "correctement". (0 < 3) donne un booléen, mais en C un booléen est juste un entier ayant pour valeurs 0 ou 1, donc on peut comparer ce booléen de la même manière avec 2. Or, (0 < 2) et (1 < 2) renvoient toujours "1", quoi qu'il arrive. Donc ce test est juste foireux.
Ceci fait ressortir à nouveau l'importance de mettre des parenthèses, mais aussi les limites du typage en C : comme tout est un peu du même type (tout est plus ou moins entier, sauf les pointeurs, mais si on veut on peut les caster de toute façon), on peut écrire des opérations qui sont parfaitement fausses. Le même code en Java ne compilerait a priori pas (je n'ai pas testé), puisque la comparaison entre un booléen et un entier n'est pas autorisée.
Une fois encore, il ne faut surtout pas partir du principe que ça fonctionne si on n'a pas vérifié que le langage le supporte ! Et une compilation réussie ne garanti en aucun cas que le code va faire ce qu'on pense qu'il va faire !
Aucun trackbacks pour l'instant