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

Affectation et opérateurs logiques

26 réponses
Avatar
Romuald
Bonjour,

L'autre jour j'ai pu =E9crire, en pensant que c'=E9tait tout =E0 fait l=E9g=
al,
quelque chose comme :

v =3D a + (p !=3D NULL) ? 0 : 1;

J'ai =E9t=E9 surpris de voir que le r=E9sultat n'=E9tait pas celui que
j'attendais. Je me suis mis =E0 chercher (dans la norme C99) o=F9 =E9tait l=
e
comportement ind=E9fini l=E0-dedans et je pense l'avoir trouv=E9 :

A propos de l'affectation : "The side effect of updating the stored
value of the left operand shall
occur between the previous and the next sequence point." et "If an
attempt is made to modify
the result of an assignment operator or to access it after the next
sequence point, the
behavior is undefined."
Sachant que, =E0 propos de l'op=E9rateur ternaire : "The first operand is
evaluated; there is a sequence point after its evaluation.".

Apr=E8s l'=E9valuation de "p !=3D NULL" l'affectation n'est pas termin=E9e =
et
pourtant c'est l=E0 le "sequence point" suivant, d'o=F9 le comportement
ind=E9fini.

Je pense que j'ai bon ?

Vu comment les op=E9rateurs de comparaison && et || fonctionnent =E7a
voudrait dire qu'on ne peux pas affecter =E0 une variable le r=E9sultat de
ces op=E9rateurs ? Tout porte =E0 le croire mais j'ai du mal =E0 comprendre
pourquoi le langage l'interdirait* ?

Merci d'avance !

* Ok, c'est juste "comportement ind=E9fini", c'est pas "interdit", mais
on se comprend !

10 réponses

1 2 3
Avatar
Jean-marc
Romuald wrote:
J'ai bien compris que dans mon exemple il y a un problème de priorité.



Oui.

Cependant il me sert surtout de prétexte pour tenter de comprendre les
fameuses deux citations, et notamment en quoi le "next sequence point"
de l'affectation n'est pas celui de l'opérateur ?: .



ok.

J'y ai encore réfléchis depuis et j'ai trouvé une autre manière de
lire cette phrase ("The side effect of updating the stored value of
the left operand shall occur between the previous and the next
sequence point.").



<snip>

Une bonne entrée en matière, à la fois simple et didactique. Il suffit de
lire à tête reposée :
http://c-faq.com/expr/seqpoints.html

A voir aussi:
http://en.wikipedia.org/wiki/Sequence_point

Franchement, il n'y pas de quoi se prendre la tête : c'est simple et
il y a peu de cas à étudier, finalement.

Merci d'avance pour vos remarques.



De rien.

--
Jean-marc
Avatar
Antoine Leca
Romuald écrivit :
Cependant il me sert surtout de prétexte pour tenter de comprendre les
fameuses deux citations, et notamment en quoi le "next sequence point"
de l'affectation n'est pas celui de l'opérateur ?: .



La notion de point de séquence suivant est propre à l'opérateur
d'affectation, et doit s'interpréter dans le contexte syntaxique de
chaque opérateur (donc des opérateur &&, ||, virgule, etc. qui
l'entourent). Quant à l'opérateur ?:, il crée un point de séquence
intermédiaire, celui qui trie entre l'expression de contrôle (celle
avant le ?) et l'expression cible, qui est soit celle entre ? et :, soit
celle après le :. Si tu as un opérateur d'affectation avant le point de
séquence de contrôle, comme dans (a=b)?0:1, alors oui, ce point de
contrôle sera le point de séquence suivant pour l'opérateur d'affectation.


Donc dans :
v = a + (p != NULL) ? 0 : 1;
la fin de l'affectation est le point-virgule et le "next sequence
point" est justement celui induit par le point-virgule. Il n'y a donc
pas de problème avec cette construction.



Oui.


Autre exemple, en admettant que l'ordre d'évaluation soit de gauche à
droite,



Attention : l'ordre d'évaluation (et les priorités d'opérateurs) n'a
rien à voir avec les points de séquence !

quelque chose comme :
b = 2;
a = (b = 3) + b;
pose problème



Oui. Mais
b = 2;
a = b + (b = 3);
pose exactement le même problème.
Le problème est que le comportement est /indéfini/ : il est impossible
de prévoir si le résultat dans a sera 5 ou 6. Pour un compilateur donné,
tu as des chances d'obtenir 5 dans un cas et 6 dans l'autre, ce qui va à
l'encontre du principe de commutativité de l'addition.

Dans ce cas, la norme prescrit que le résultat peut être n'importe quoi,
y compris autre chose que 5 ou 6, et y compris que l'exécution puisse
s'arrêter ou qu'il pleuve des grenouilles ; en gros, il est proscrit
d'écrire du code comme cela car ce n'est pas portable.


Et donc :

a = (b = 3) + ((1) ? b : b);

est valide car le "next sequence point" associé à l'affectation (b > 3) est ici celui de l'opérateur ?:



Non. L'opérateur ?: est à l'intérieur d'une paire de parenthèses, qui
font obstacle à la propagation des point de séquence ; vu autrement, le
point de séquence de contrôle de l'opérateur ?: a son horizon gauche
masqué par la parenthèse ouvrante. Le point de séquence suivant est ici
encore le ; final (et il y encore un problème).


De ce que j'ai lu apparemment je ne suis pas le seul troublé !



Certes non. Le sujet est vraiment technique, et même les experts
ressentent le besoin de se concentrer lorsqu'on aborde le thème pour
éviter de se tromper.


Antoine
Avatar
Antoine Leca
Jean-marc écrivit :
Une bonne entrée en matière, à la fois simple et didactique. Il suffit de
lire à tête reposée :
http://c-faq.com/expr/seqpoints.html



Très bonne référence, c'est sobre et précis.


Antoine
Avatar
Jean-Marc Bourguet
Antoine Leca writes:

De ce que j'ai lu apparemment je ne suis pas le seul troublé !



Certes non. Le sujet est vraiment technique, et même les experts
ressentent le besoin de se concentrer lorsqu'on aborde le thème pour
éviter de se tromper.



Par exemple, les points de sequencement ne sont pas tous classes par un
ordre total. Et en prime la formulation de la norme n'est pas toujours
aussi claire que desirable.

Il y a eu une serie de tentative de clarifications. La derniere en date
(et la seule qui a passe le stade de papier preparatoire) est celle du
C++ qui abandonne totalement la notion de point de sequencement en la
replacement par un ordre partiel sur les operations (plus d'autres
choses car le travail a ete fait pour avoir une definition precise dans
le cadre du multithread). Ma comprehension est qu'elle devrait etre
reprise dans la prochaine norme C.

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
espie
In article ,
Jean-Marc Bourguet wrote:
Il y a eu une serie de tentative de clarifications. La derniere en date
(et la seule qui a passe le stade de papier preparatoire) est celle du
C++ qui abandonne totalement la notion de point de sequencement en la
replacement par un ordre partiel sur les operations (plus d'autres
choses car le travail a ete fait pour avoir une definition precise dans
le cadre du multithread). Ma comprehension est qu'elle devrait etre
reprise dans la prochaine norme C.



C'est pas trop tot...

Malgre toute la consideration que je peux porter au C++, greffer une
semantique precise de gestion de constructeurs/destructeurs, operateurs
definis par l'utilisateur et d'exceptions au dessus de la semantique de
base du C etait une vaste connerie.

Maintenant, ca serait toujours bien si les comites C et C++ arrivaient un
peu plus a travailler parfois ensemble, ca commence a etre penible d'avoir
chaque redefinition de chaque langage qui se rend fortement incompatible
avec le reste...

... sans compter la propension de la normalisation C++ a rajouter des tonnes
de trucs peu comprehensibles par le commun des mortels et a la semantique
souvent douteuse...


(fin du rant, vous pouvez reprendre votre lecture normale).
Avatar
Wykaaa
Marc Espie a écrit :
In article ,
Jean-Marc Bourguet wrote:
Il y a eu une serie de tentative de clarifications. La derniere en date
(et la seule qui a passe le stade de papier preparatoire) est celle du
C++ qui abandonne totalement la notion de point de sequencement en la
replacement par un ordre partiel sur les operations (plus d'autres
choses car le travail a ete fait pour avoir une definition precise dans
le cadre du multithread). Ma comprehension est qu'elle devrait etre
reprise dans la prochaine norme C.



C'est pas trop tot...

Malgre toute la consideration que je peux porter au C++, greffer une
semantique precise de gestion de constructeurs/destructeurs, operateurs
definis par l'utilisateur et d'exceptions au dessus de la semantique de
base du C etait une vaste connerie.

Maintenant, ca serait toujours bien si les comites C et C++ arrivaient un
peu plus a travailler parfois ensemble, ca commence a etre penible d'avoir
chaque redefinition de chaque langage qui se rend fortement incompatible
avec le reste...

... sans compter la propension de la normalisation C++ a rajouter des tonnes
de trucs peu comprehensibles par le commun des mortels et a la semantique
souvent douteuse...



On pourrait même dire qu'au fil des révisions, les choses n'ont fait
qu'empirer et que les programmes écrits avec les dernières "nouveautés"
deviennent quasiment incompréhensibles pour qui ne possède pas la
"norme" sur le bout des doigts (et encore...).

Quant au C, pardon de me répéter, mais je pense très sincèrement que
c'est un des langages de programmation le plus mal foutu (et je le redis
encore, j'ai fait un compilateur C et je connaissais la première norme
ANSI quasiment par coeur. Je sais donc de quoi je parle...).

Ceci est surtout la conséquence des discussions de "marchands de tapis",
donc des compromis, qui sont la règles dans les comités de
normalisation, chacun essayant de défendre son point de vue et pour ne
froisser personne, on adopte des solutions bancales plutôt que de se
conformer à des modèles solides (comme le lambda-calcul, la théorie des
types, etc.).
La science informatique ne devrait pas se bâtir à coups de compromis...
C'est d'ailleurs une des raisons pour lesquelles on ne peut qualifier
l'informatique de science que du bout des lèvres...
Avatar
Vincent Lefevre
Dans l'article <iib63j$16a$,
Antoine Leca écrit:

Jean-marc écrivit :
> Une bonne entrée en matière, à la fois simple et didactique. Il suffit de
> lire à tête reposée :
> http://c-faq.com/expr/seqpoints.html

Très bonne référence, c'est sobre et précis.



Mais ça ne parle pas des cas les plus tordus, comme: a[a[i]] = 0;
dans le cas où a[i] == i.

--
Vincent Lefèvre - Web: <http://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / Arénaire project (LIP, ENS-Lyon)
Avatar
Jean-Marc Bourguet
Vincent Lefevre writes:

Mais ça ne parle pas des cas les plus tordus, comme: a[a[i]] = 0;
dans le cas où a[i] == i.



Je ne vois pas de probleme ici. (On ne se sert pas de ce qui est modifie
pour autre chose que la determination de ce qui est modifie ou de sa
nouvelle valeur, ce qui me semble-t'il est autorise).

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Jean-marc
Vincent Lefevre wrote:
Dans l'article <iib63j$16a$,
Antoine Leca écrit:

Jean-marc écrivit :
Une bonne entrée en matière, à la fois simple et didactique. Il
suffit de lire à tête reposée :
http://c-faq.com/expr/seqpoints.html





Très bonne référence, c'est sobre et précis.



Mais ça ne parle pas des cas les plus tordus


........................................^^^^^^

En effet... Et il y a peut être une *bonne* raison
à cela :o)

--
Jean-marc
Avatar
Vincent Lefevre
Dans l'article ,
Jean-Marc Bourguet écrit:

Vincent Lefevre writes:

> Mais ça ne parle pas des cas les plus tordus, comme: a[a[i]] = 0;
> dans le cas où a[i] == i.

Je ne vois pas de probleme ici. (On ne se sert pas de ce qui est modifie
pour autre chose que la determination de ce qui est modifie ou de sa
nouvelle valeur, ce qui me semble-t'il est autorise).



La norme dit (6.5#2): "Between the previous and next sequence point
an object shall have its stored value modified at most once by the
evaluation of an expression. Furthermore, the prior value shall be
read only to determine the value to be stored."

Considérons l'objet a[i] et supposons a[i] == i. La valeur stockée
va être modifiée. Donc la lecture de a[i] ne doit servir qu'à
déterminer la valeur à être stockée (pas à autre chose, cf le
"only"). Mais dans le code ci-dessus, la lecture de a[i] sert
à tout autre chose: à déterminer l'adresse de l'objet.

--
Vincent Lefèvre - Web: <http://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / Arénaire project (LIP, ENS-Lyon)
1 2 3