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

Priorité et associativité des opérateurs

125 réponses
Avatar
Greydavayar
Bonjour a tous,

je lis partout le terme "d'associativit=E9" des op=E9rateurs ainsi que le
teme de "priorit=E9" des op=E9rateurs je pense avoir compris celui de la
priorit=E9 mais cette notion d'associativit=E9 reste tr=E8s (trop) floue
pour moi et je ne trouve rien qui l'explique clairement sur le net.

Bonne soir=E9e

10 réponses

1 2 3 4 5
Avatar
JKB
Le 06 Sep 2010 11:06:02 +0200,
Jean-Marc Bourguet écrivait :
"" writes:

Jean-Marc Bourguet wrote:

> (Marc Espie) writes:
>
>> In article <i5vilk$k86$,
>> wrote:
>> >Petit quizz : comment sont évaluées :
>> > a - b - c ?
>> > a / b / c ?
>> >
>> >P.S: à mon avis, un programmeur écrivant des expressions comme
>> >ci-dessus mérite un magistral coup de pied au cul !
>>
>> A mon avis, quelqu'un qui ne sait pas lire les expressions ci-dessus et
>> qui se proclame "programmeur" merite un petit retour sur ses bancs
>> d'ecole, section arithmetique elementaire...
>
> Ou alors il a trop fait d'APL recemment. :-)

comme tu le fais justement remarquer un peu plus haut, les règles
d'associativité sont dépendantes du langage et donc je reste persuadé qu'un
programmeur qui est capable d'écrire des expressions commmes celles que
j'ai mentionné ci-dessus ne cherche pas à avoir du code facile à maintenir
(même dans plusieurs années) mais juste à montrer sa maîtrise du langage.



Je suis plutot de l'avis de Marc, un programmeur qui a besoin de
parentheses sur ces expressions est incompetant dans ce langage. Ce n'est
pas une subtilite.



Ouaips. Sauf que lorsque tu travailles dans plusieurs langages qui
sont orthogonaux, tu vas très vite dans le mur. Par ailleurs, je
connais des compilos (gcc pour ne pas le nommer) qui d'une version à
l'autre se comportent différemment. Remarque, il renvoit un warning.
En d'autres termes, je ne vois pas l'intérêt d'économiser une
parenthèse lorsque cela évite une étape de debug qui peut être assez
laborieuse.

Personnellement, lorsque je suis obligé de relire du code avec des
trucs comme :

e = a - b - c + d;

avec des variables qui peuvent être de types différents ou de
valeurs absolues franchement différentes lorsqu'il s'agit de
flottants, je vois rouge et je n'ai même pas envie de rechercher les
autres bugs !

Ce genre d'expression est une calamité en analyse numérique (erreurs
d'arrondis) et surtout n'est pas vraiment reproductible d'un compilo
à un autre. J'ai des très vieux souvenirs de ce genre de chose entre
un gcc 2.7.2.3 et un Turbo C. Et j'ajouterais que ce n'est pas lisible.

Enfin, chacun fait ce qu'il veut.

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
espie
In article <i6278j$2ctc$,
wrote:
A mon avis, quelqu'un qui ne sait pas lire les expressions ci-dessus et
qui se proclame "programmeur" merite un petit retour sur ses bancs
d'ecole, section arithmetique elementaire...



Ou alors il a trop fait d'APL recemment. :-)



comme tu le fais justement remarquer un peu plus haut, les règles
d'associativité sont dépendantes du langage et donc je reste persuadé qu'un
programmeur qui est capable d'écrire des expressions commmes celles que
j'ai mentionné ci-dessus ne cherche pas à avoir du code facile à maintenir
(même dans plusieurs années) mais juste à montrer sa maîtrise du langage.



Non mais, n'importe quoi. La *totalite* des langages proceduraux a la C
ont *exactement* les memes regles pour les quatre operations arithmetiques
elementaires (comme par exemple, C, C++, objective C, java, pascal, ada,
icon, python, perl, php, javascript, caml, et j'en passe...)

Autant rajouter des parentheses pour a peu pres tout le reste a un sens,
autant en mettre sur ce type d'expression elementaire demontre juste une
ignorance crasse des conventions habituelles.

Si tu appelles "ne pas en mettre" "la maitrise du langage", eh bien on n'est
pas rendus.

Je sais qu'il y a des projets ou on embauche des gars suffisamment neuneus
pour exiger qu'ils parenthesent absolument tout. J'espere juste que ces
projets ont une TRES BONNE review de code, ou utilisent autre chose que C,
parce que si les gars ont des problemes avec ca, on va rigoler lorsqu'ils
vont utiliser des cast.


On n'est pas en train de parler d'APL, ni de lisp, ni de PostScript, ni
de SmallTalk, mais bien de C.

Utiliser des conventions qui ont ete choisies a l'identique dans tous les
langages du meme style, ca me parait juste etre le ba-ba de la programmation
dans ces langages.
Avatar
Antoine Leca
JKB écrivit :
Le 06 Sep 2010 11:06:02 +0200, Jean-Marc Bourguet écrivait :
a - b - c ?
a / b / c ?








Je suis plutot de l'avis de Marc, un programmeur qui a besoin de
parentheses sur ces expressions est incompetant dans ce langage. Ce n'est
pas une subtilite.



Ouaips. Sauf que lorsque tu travailles dans plusieurs langages qui
sont orthogonaux, tu vas très vite dans le mur.



Un programmeur qui programme simultanément sur plusieurs langages, ce
n'est pas courant. S'il faut penser à ces gens-là, plus à tous les
groupes spéciaux ayant au moins la même fréquence lorsque tu programmes,
les chances d'aller dans le mur sont effectivement très grandes : même
sans aller chercher des trucs aussi compliqués que des
programmeurs-qui-travaillant-sur-plusieurs-langages-ne-savent-pas-lire-
des-expressions-avec-deux-opérateurs-ou-plus, on voit que la tendance
actuelle des règles anti-possibles-potentiels-dépassements-virtuels de
tampons (avec des conséquences comme la fonction gets_s), ÀMHA, amène le
langage avec une certaine vitesse en direction d'un édifice artificiel
composé de parpaings... reste à voir si on va rentrer dedans.


Par ailleurs, je connais des compilos (gcc pour ne pas le nommer)
qui d'une version à l'autre se comportent différemment.



Un compilo qui se comporte différemment d'une version à l'autre sur la
priorité ou l'associativité des opérateurs risque d'avoir une durée de
vie courte. En C, depuis 1989, c'est encore plus simple, c'est juste une
faute de conformité majeure.


En d'autres termes, je ne vois pas l'intérêt d'économiser une
parenthèse lorsque cela évite une étape de debug qui peut être assez
laborieuse.



Réfléchissons un peu : tu es en train de débogger, tu tombes sur du code
étranger qui utilise une telle expression ; des deux évaluations
possibles, l'une est stupide : est-ce laborieux que de l'écarter d'office ?

Personnellement, lorsque je suis obligé de relire du code avec des
trucs comme :

e = a - b - c + d;

avec des variables qui peuvent être de types différents ou de
valeurs absolues franchement différentes lorsqu'il s'agit de
flottants, je vois rouge et je n'ai même pas envie de rechercher les
autres bugs !



Sauf que là, tu as changé le problème et la possible solution : si tu es
confronté à un souci à cause des types flottants et des arrondis (ou
même tout simplement à cause des types et donc des domaines différents),
la solution ne viendra pas de parenthèses, mais de transtypages et de
réorganisation de l'expression, ou même de décomposer en plusieurs
opérations distinctes.

Et oui, cela peut être un souci avec du code d'analyse numérique en
comportement aux limites ; et il est fort possible que le code ci-dessus
n'ait PAS été testé de manière adéquate : mais j'ai tendance à penser
que si cela devient un objectif, avant de rentrer dans la phase de
débogage de possibles erreurs, on pourrait commencer par une analyse du
problème... qui dans mon cas débouchera sur des commentaires
accompagnant l'expression, voire des assertions validant les hypothèses
attendues (en supposant que l'expression est correcte).


Antoine
Avatar
Pierre Maurette
, le 06/09/2010 a écrit :

[...]

Petit quizz : comment sont évaluées :
a - b - c ?
a / b / c ?

P.S: à mon avis, un programmeur écrivant des expressions comme
ci-dessus mérite un magistral coup de pied au cul !









[...]

comme tu le fais justement remarquer un peu plus haut, les règles
d'associativité sont dépendantes du langage et donc je reste persuadé qu'un
programmeur qui est capable d'écrire des expressions commmes celles que
j'ai mentionné ci-dessus ne cherche pas à avoir du code facile à maintenir
(même dans plusieurs années) mais juste à montrer sa maîtrise du langage.

J'ai tellement vu de bugs juste parce qu'un programmeur maladroit, croyant
maitriser les subtilités d'un langage, préférait faire "pédant et
compliqué" alors qu'il aurait du faire "simple et clair". Le "obfuscated C
code contest" est une preuve de maitrise indéniable et une activité très
amusante, mais j'aurais de la peine à la recommander pour les vrais
programmes.



Je serais assez d'accord sur le fond de votre intervention, bien que
moins dur que vous. Il y a manifestement dans certaines écritures,
certains C-ismes, un plaisir de chapelle.
Mais les exemples que vous proiposez sont on ne peut plus mal choisis.
Ils ne proposent aucune sorte d'ambiguïté. Ils sont en accord avec
l'arithmétique de base, le bon sens et les habitudes de M. Toulemonde
et sa calculette de chez Auchan. Qui est rarement RPN.

Par curiosité, j'ai regardé dans quels cas un gcc 4.4.1 juste Wall me
proposait une alerte (toujours un warning proposant des parenthèses, en
fait un warning pour suspicion d'erreur, inutile si tous les
programmeurs étaient parfaits).

Rien bien entendu pour
d = a - b - c;
ni:
e = a / b / c;

Un warning attendu dans ce cas:
if(a = b)...
qui se tait avec:
if((a = b) != 0)...
ou simplement (puisque if(a) est admis):
if((a = b))...

Un warning pour:
if(a == b == c)...
Le programmeur a-t-il bien voulu comparer c au résultat de la
comparaison a == b ? Et quand bien même, s'est-il interrogé sur le cas
où c ne vaut ni 0 ni 1 ?
if((a == b) == c)...
fait taire le warning. Je trouve ça presque insuffisant, à moins que c
soit clairement le résultat d'une opération logique. Ecrire plutôt:
if((a == b) == !!c)...
ou carrément (si if(a == b == c) n'était pas une erreur:
if(((a == b) && (c == 1)) || ((a != b) && (c == 0)))...
ou plus léger et que je lis mieux:
if(a == b ? c == 1 : c == 0)...

Enfin, j'ai remarqué que:
a | b & c | d
a & b | c & d
a || b && c || d
a && b || c && d
génèrent un warning, alors que:
a + b * c + d
a * b + c * d
laissent gcc muet. Est-ce logique ?

--
Pierre Maurette
Avatar
JKB
Le Mon, 06 Sep 2010 13:51:09 +0200,
Antoine Leca écrivait :
JKB écrivit :
Personnellement, lorsque je suis obligé de relire du code avec des
trucs comme :

e = a - b - c + d;

avec des variables qui peuvent être de types différents ou de
valeurs absolues franchement différentes lorsqu'il s'agit de
flottants, je vois rouge et je n'ai même pas envie de rechercher les
autres bugs !



Sauf que là, tu as changé le problème et la possible solution : si tu es
confronté à un souci à cause des types flottants et des arrondis (ou
même tout simplement à cause des types et donc des domaines différents),
la solution ne viendra pas de parenthèses, mais de transtypages et de
réorganisation de l'expression, ou même de décomposer en plusieurs
opérations distinctes.

Et oui, cela peut être un souci avec du code d'analyse numérique en
comportement aux limites ; et il est fort possible que le code ci-dessus
n'ait PAS été testé de manière adéquate : mais j'ai tendance à penser
que si cela devient un objectif, avant de rentrer dans la phase de
débogage de possibles erreurs, on pourrait commencer par une analyse du
problème... qui dans mon cas débouchera sur des commentaires
accompagnant l'expression, voire des assertions validant les hypothèses
attendues (en supposant que l'expression est correcte).



Ça ne change rien au fait que des parenthèses dans le cas

a - b - c

pour avoir

a - (b + c)

est largement plus clair.

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
JKB
Le Mon, 06 Sep 2010 14:51:01 +0200,
Pierre Maurette écrivait :
, le 06/09/2010 a écrit :

[...]

Petit quizz : comment sont évaluées :
a - b - c ?
a / b / c ?

P.S: à mon avis, un programmeur écrivant des expressions comme
ci-dessus mérite un magistral coup de pied au cul !









[...]

comme tu le fais justement remarquer un peu plus haut, les règles
d'associativité sont dépendantes du langage et donc je reste persuadé qu'un
programmeur qui est capable d'écrire des expressions commmes celles que
j'ai mentionné ci-dessus ne cherche pas à avoir du code facile à maintenir
(même dans plusieurs années) mais juste à montrer sa maîtrise du langage.

J'ai tellement vu de bugs juste parce qu'un programmeur maladroit, croyant
maitriser les subtilités d'un langage, préférait faire "pédant et
compliqué" alors qu'il aurait du faire "simple et clair". Le "obfuscated C
code contest" est une preuve de maitrise indéniable et une activité très
amusante, mais j'aurais de la peine à la recommander pour les vrais
programmes.



Je serais assez d'accord sur le fond de votre intervention, bien que
moins dur que vous. Il y a manifestement dans certaines écritures,
certains C-ismes, un plaisir de chapelle.
Mais les exemples que vous proiposez sont on ne peut plus mal choisis.
Ils ne proposent aucune sorte d'ambiguïté. Ils sont en accord avec
l'arithmétique de base, le bon sens et les habitudes de M. Toulemonde
et sa calculette de chez Auchan. Qui est rarement RPN.

Par curiosité, j'ai regardé dans quels cas un gcc 4.4.1 juste Wall me
proposait une alerte (toujours un warning proposant des parenthèses, en
fait un warning pour suspicion d'erreur, inutile si tous les
programmeurs étaient parfaits).

Rien bien entendu pour
d = a - b - c;
ni:
e = a / b / c;

Un warning attendu dans ce cas:
if(a = b)...



Qui est malheureusement parfaitement légal. Je me bats tous les
jours contre ce genre de conneries parce qu'il y a des OS ou NULL ne
vaut pas zéro ! Au hasard VMS avec certaines versions antiques de
DEC C.

qui se tait avec:
if((a = b) != 0)...



Normal.

ou simplement (puisque if(a) est admis):
if((a = b))...



Normal aussi même si ça devrait être proscrit.

Un warning pour:
if(a == b == c)...
Le programmeur a-t-il bien voulu comparer c au résultat de la
comparaison a == b ? Et quand bien même, s'est-il interrogé sur le cas
où c ne vaut ni 0 ni 1 ?
if((a == b) == c)...
fait taire le warning. Je trouve ça presque insuffisant, à moins que c
soit clairement le résultat d'une opération logique. Ecrire plutôt:
if((a == b) == !!c)...



Troll detected ! Le C ne fait pas la différence entre des opérations
logiques et des opérations bit à bit. Je connais même un compilo C
pour lequel !!c vaut toujours c (je n'ai pas dit qu'il respectait
les specs).

ou carrément (si if(a == b == c) n'était pas une erreur:
if(((a == b) && (c == 1)) || ((a != b) && (c == 0)))...
ou plus léger et que je lis mieux:
if(a == b ? c == 1 : c == 0)...

Enfin, j'ai remarqué que:
a | b & c | d
a & b | c & d
a || b && c || d
a && b || c && d
génèrent un warning, alors que:
a + b * c + d
a * b + c * d
laissent gcc muet. Est-ce logique ?



Oui. Il n'y a aucun problème là-dedans. Ce qui est litigieux, mais
aussi en mathématiques de base, ce sont des expressions comme

a - b - c

puisque le résultat est différent selon l'associativité. C'est dans
ce cas qu'il faut mettre des parenthèses pour la lisibilité du
code. On a beau jeu de dire que l'associativité se fait de gauche à
droite. Lorsqu'on a une expression simple, c'est trivial. Lorsque ça
devient un peu plus complexe, c'est tout de suite un nid à problème
qu'on peut facilement éviter !

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Marc
On 6 sep, 15:09, JKB wrote:
        Oui. Il n'y a aucun problème là-dedans. Ce qui est li tigieux, mais
        aussi en mathématiques de base, ce sont des expressions comme

                a - b - c

        puisque le résultat est différent selon l'associativi té. C'est dans
        ce cas qu'il faut mettre des parenthèses pour la lisibi lité du
        code. On a beau jeu de dire que l'associativité se fait de gauche à
        droite. Lorsqu'on a une expression simple, c'est trivial. Lorsque ça
        devient un peu plus complexe, c'est tout de suite un nid à problème
        qu'on peut facilement éviter !



Euh, en maths, personne ne parenthèse jamais une expression comme a-b-
c. Il faut une dépendance pathologique au LISP pour vouloir lire des
choses comme ((a-b)-c)-d
Avatar
espie
In article , JKB <invalid> wrote:
Un warning attendu dans ce cas:
if(a = b)...



Qui est malheureusement parfaitement légal. Je me bats tous les
jours contre ce genre de conneries parce qu'il y a des OS ou NULL ne
vaut pas zéro ! Au hasard VMS avec certaines versions antiques de
DEC C.



Tu parles de C pre-K&R, la.

NULL vaut (une variante de 0). Meme si la representation du pointeur nul n'est
pas "tout a zero". En C standard, si on declare char *p;
le pointeur nul rendra toujours vrai le test if (p == 0),
puisque, dans cette expression, le 0 n'est pas un zero numerique, mais un
zero dans un contexte pointeur, donc un pointeur nul, independamment de
sa representation !

Le "tous les jours" me surprend quand meme un peu.

Etant dans un monde adepte de vieilleries, je ne croise heureusement pas
tant que ca des compilo pre-K&R...
Avatar
Marc Boyer
Le 06-09-2010, JKB a écrit :
Le Mon, 06 Sep 2010 14:51:01 +0200,
Un warning attendu dans ce cas:
if(a = b)...



Qui est malheureusement parfaitement légal. Je me bats tous les
jours contre ce genre de conneries parce qu'il y a des OS ou NULL ne
vaut pas zéro ! Au hasard VMS avec certaines versions antiques de
DEC C.



Sauf que même si NULL ne vaut pas 0, sa conversion implicite
dans ce contexte là doit se faire vers 0 (pour ce qui est du C,
en DEC C, je ne sais pas).

Marc Boyer
--
En prenant aux 10% des francais les plus riches 12% de leurs revenus,
on pourrait doubler les revenus des 10% les plus pauvres.
http://www.inegalites.fr/spip.php?article1&id_mot0
Avatar
Antoine Leca
JKB a écrit :
Le Mon, 06 Sep 2010 13:51:09 +0200,
Antoine Leca écrivait :
JKB écrivit :
Personnellement, lorsque je suis obligé de relire du code avec des
trucs comme :

e = a - b - c + d;

avec des variables qui peuvent être de types différents ou de
valeurs absolues franchement différentes lorsqu'il s'agit de
flottants, je vois rouge et je n'ai même pas envie de rechercher les
autres bugs !



Sauf que là, tu as changé le problème et la possible solution : si tu es
confronté à un souci à cause des types flottants et des arrondis (ou
même tout simplement à cause des types et donc des domaines différents),
la solution ne viendra pas de parenthèses, mais de transtypages et de
réorganisation de l'expression, ou même de décomposer en plusieurs
opérations distinctes.

Et oui, cela peut être un souci avec du code d'analyse numérique en
comportement aux limites ; et il est fort possible que le code ci-dessus
n'ait PAS été testé de manière adéquate : mais j'ai tendance à penser
que si cela devient un objectif, avant de rentrer dans la phase de
débogage de possibles erreurs, on pourrait commencer par une analyse du
problème... qui dans mon cas débouchera sur des commentaires
accompagnant l'expression, voire des assertions validant les hypothèses
attendues (en supposant que l'expression est correcte).



Ça ne change rien au fait que des parenthèses dans le cas

a - b - c

pour avoir

a - (b + c)

est largement plus clair.

JKB

1 2 3 4 5