Greg's Devblog Par un développeur, pour les développeurs

29sept/102

Importance des parenthèses

J'ai déjà eu le cas d'un programmeur qui ne mettait quasiment jamais de parenthèses, genre "ça sert à rien". Un if peut rapidement avoir une tête du style :

if (a == 2 && b == 3 && c == 4 && ... && z == -2)

Je trouve ça relativement peu lisible, au final, et je rajoute toujours les parenthèses qui vont bien. Voici donc un petit code intéressant pour illustrer les soucis potentiels :

printf("%i %i %i\n", (-2)&0xFF, 254, (-2)&0xFF == 254);

Alors... A votre avis, qu'est-ce qui va être affiché ?

  • (-2)&0xFF affiche 254
  • 254 affiche... 254 (ok, c'était facile)
  • (-2)&0xFF == 254 affiche... 0 !

Et oui, on pourrait s'attendre à ce que ça affiche 1 (puisque (-2)&0xFF vaut 254), mais en pratique ce n'est pas le cas. Alors pourquoi ?

Tout simplement parce que ce qu'on obtient comme résultat est en fait le résultat de (-2) & (0xFF == 254). Comme 0xFF vaut 255, (0xFF == 254) vaut 0, et donc (-2) & 0 vaut 0... Dommage !

En fait, il vaut mieux mettre des parenthèses inutiles que de ne pas en mettre du tout... Car même avec trop de parenthèses, on sait ce qu'on va obtenir, alors que si on les retire cela signifie qu'on se repose complètement sur la priorité décidée par le compilo (ou plutôt la norme). Pas forcémnet une bonne chose à faire si on ne maitrise pas parfaitement le sujet !

Pour rebondir un peu sur ce cas (qui parait un peu improbable à cause du -2 qui traine), voici un que j'ai construit et qui renvoie toujours TRUE :

1&0xFF == 255
Commentaires (2) Trackbacks (0)
  1. (1&0xFF == 255) est un test particulièrmenet puissant. Personnellement, je n’ai jamais compris pourquoi Kerninghan et Ritchie ont donné aux opérations bit-à-bit la priorité sur les tests , mais c’est comme ça … résultat, il faudrait écrire (x & 0xff) == 0xff pour ne pas avoir de blague, de même qu’il faut écrire (x+2) * 4.

    L’unique autre piège de ce genre a lieu entre les opérations additives et les décalages. Puisque (x << 1) fait en fait (x * 2), il est tentant de vouloir écrire (x << 8 + y << 16) pour (x * 256 + y * 65536), mais ça ne marchera pas. (x<<8) + (y<<16) "does the trick".

    En bref, quand on reprend un langage qu'on a pas pratiqué depuis un moment, mieux vaut reprendre la table "priorité des opérateurs" et vérifier qu'on a bien les choses clairement en tête.
    Vive la notation polonaise inverse :-P

    • D’ailleurs je vais en poster un autre dans le même genre tout à l’heure qui est pas mal :p (uniquement pour les débutants)


Laisser un commentaire


Aucun trackbacks pour l'instant