Affectation et opérateurs logiques
Le
Romuald
Bonjour,
L'autre jour j'ai pu écrire, en pensant que c'était tout à fait lég=
al,
quelque chose comme :
v = a + (p != NULL) ? 0 : 1;
J'ai été surpris de voir que le résultat n'était pas celui que
j'attendais. Je me suis mis à chercher (dans la norme C99) où était l=
e
comportement indéfini là-dedans et je pense l'avoir trouvé :
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, à propos de l'opérateur ternaire : "The first operand is
evaluated; there is a sequence point after its evaluation.".
Après l'évaluation de "p != NULL" l'affectation n'est pas terminée =
et
pourtant c'est là le "sequence point" suivant, d'où le comportement
indéfini.
Je pense que j'ai bon ?
Vu comment les opérateurs de comparaison && et || fonctionnent ça
voudrait dire qu'on ne peux pas affecter à une variable le résultat de
ces opérateurs ? Tout porte à le croire mais j'ai du mal à comprendre
pourquoi le langage l'interdirait* ?
Merci d'avance !
* Ok, c'est juste "comportement indéfini", c'est pas "interdit", mais
on se comprend !
L'autre jour j'ai pu écrire, en pensant que c'était tout à fait lég=
al,
quelque chose comme :
v = a + (p != NULL) ? 0 : 1;
J'ai été surpris de voir que le résultat n'était pas celui que
j'attendais. Je me suis mis à chercher (dans la norme C99) où était l=
e
comportement indéfini là-dedans et je pense l'avoir trouvé :
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, à propos de l'opérateur ternaire : "The first operand is
evaluated; there is a sequence point after its evaluation.".
Après l'évaluation de "p != NULL" l'affectation n'est pas terminée =
et
pourtant c'est là le "sequence point" suivant, d'où le comportement
indéfini.
Je pense que j'ai bon ?
Vu comment les opérateurs de comparaison && et || fonctionnent ça
voudrait dire qu'on ne peux pas affecter à une variable le résultat de
ces opérateurs ? Tout porte à le croire mais j'ai du mal à comprendre
pourquoi le langage l'interdirait* ?
Merci d'avance !
* Ok, c'est juste "comportement indéfini", c'est pas "interdit", mais
on se comprend !

Poser une question


Sans contexte, ca va etre un peu dur. C'est quoi les declarations de
v, a, p dans ton programme ?
Et d'ou sort NULL ? c'est le NULL des entetes standards, ou un NULL que
tu as defini tout seul ?
Voilà un programme complet :
#include
int main(void) {
int v;
int a = 1;
int* p = NULL;
v = a + (p != NULL) ? 0 : 1;
printf("%dn", v);
return 0;
}
(J'ai compile avec GCC 4.4.3)
J'avais donne aucune info de ce genre car comme on peut le voir ça va
pas chercher aussi loin que d'aller definir son propre NULL :-).
Le probleme me semble independant des types qu'on donne, c'est juste
l'utilisation de l'operateur ternaire la au milieu.
Je vous suggère de placer des parenthèses pour forcer l'associativité
que vous souhaitez. Là, c'est (a + (p != NULL)) ? 0 : 1) donc ça vaut
toujours 0 sauf pour a == 0 où ça vaut 1.
Il y a une façon plus simple d'écrire ça.
--
Pierre Maurette
En effet j'avais pas remarque ça.
J'ai donc voulu dire "a + ((p != NULL) ? 0 : 1)".
Cependant dans les deux cas le probleme du "sequence point" se pose
toujours, non ?
Non, avec mon gcc qui est au feu, en -stdÉ9, vite fait, ça fait ce
que j'attends. Notez que si a est un int et p un pointeur, votre truc
se remplace par "a + !p".
--
Pierre Maurette