Pourquoi est f(i = -1, i = -1) un comportement indéfini?

Que j'ai lu sur l'ordre d'évaluation des violations, et ils donnent un exemple qui m'intrigue, c'.

1) Si un effet indésirable sur un scalaire objet est non-séquencés par rapport à un autre effet secondaire sur la même scalaire objet, le comportement est indéfini.

//snip
f(i = -1, i = -1); //undefined behavior

Dans ce contexte, i est un scalaire objet, ce qui signifie apparemment

Arithmétique types (3.9.1), l'énumération des types, des types pointeur, pointeur de types de membres (3.9.2), std::nullptr_t, et de cv qualifiés versions de ces types (3.9.3) sont collectivement appelés types scalaires.

Je ne vois pas comment l'énoncé est ambigu dans ce cas. Il me semble que, peu importe si le premier ou le deuxième argument est évalué en premier, i finit -1, et les deux arguments sont également -1.

Quelqu'un peut-il préciser?


Mise à JOUR

J'ai vraiment apprécier toutes les discussions. Jusqu'à présent, j'aime @harmaline réponse beaucoup car il expose les pièges et subtilités de la définition de cette déclaration, en dépit de la façon dont tout droit vers l'avant, il semble au premier coup d'œil. @acheong87 souligne certains problèmes qui surgissent lors de l'utilisation de références, mais je pense que c'est orthogonale à la non effets secondaires aspect de cette question.


RÉSUMÉ

Depuis que cette question a obtenu une tonne de l'attention, je vais résumer les principaux points et/ou des réponses. Tout d'abord, permettez-moi une petite digression à souligner que "pourquoi" peut avoir étroitement liés et pourtant subtilement différentes significations, à savoir "ce que cause", "pour quoi raison", et "pour quoi but". Je vais regrouper les réponses par lequel de ces sens de "pourquoi" ils se sont adressés.

pour quelle cause

La principale réponse ici provient de Paul Draper, avec Martin J contribuant similaire, mais pas aussi étendues de réponse. Paul Draper la réponse se résume à

C'est un comportement indéfini, car il n'est pas défini ce que le comportement est.

La réponse est dans l'ensemble très bon en termes d'expliquer ce que le C++ standard dit. Il aborde également certains liés à des cas d'UB comme f(++i, ++i); et f(i=1, i=-1);. Dans le premier des cas, il n'est pas clair si le premier argument doit être i+1 et la deuxième i+2 ou vice-versa; dans le second, il n'est pas clair si i devrait être de 1 ou de -1, après l'appel de la fonction. Deux de ces cas sont des cas d'UB, parce qu'ils relèvent de la règle suivante:

Si un effet indésirable sur un scalaire objet est séquencé par rapport à un autre effet secondaire sur la même scalaire objet, le comportement est indéfini.

Par conséquent, f(i=-1, i=-1) est également UB car il tombe sous la même règle, malgré que l'intention du programmeur est (à mon humble avis) c'est évident et sans ambiguïté.

Paul Draper rend également explicite dans sa conclusion que

Aurait-il été défini comportement? Oui. Était-il défini? No.

qui nous amène à la question "pour quelles raisons a été f(i=-1, i=-1) gauche comme un comportement indéfini?"

pour quelles raisons

Bien qu'il existe quelques oublis (peut-être imprudente) dans la norme C++, de nombreuses omissions sont bien motivés et servir un but précis. Même si je suis conscient que le but est souvent de "faire le compilateur-écrivain travail plus facile", ou "plus vite code", j'ai surtout été intéressé de savoir si il y a une bonne raison de quitter f(i=-1, i=-1) comme UB.

harmaline et supercat fournir les principales réponses qui fournissent une raison pour l'UB. Harmaline, un compilateur optimisant qui pourraient briser soi-disant atomique des opérations d'affectation en plusieurs instructions machine, et qu'il pourrait en outre interleave ces instructions pour une vitesse optimale. Cela pourrait conduire à des résultats surprenants: i finit -2 dans son scénario! Ainsi, harmaline montre comment affecter le même valeur à une variable plus d'une fois, peut avoir des effets pervers si les opérations sont séquencé.

supercat fournit un liés à l'exposition des pièges d'essayer d'obtenir f(i=-1, i=-1) de faire ce qu'il dirait qu'il devrait faire. Il souligne que sur certaines architectures, il y a de dur restrictions à l'encontre des multiples et simultanées écrit à la même adresse mémoire. Un compilateur pourrait avoir un moment difficile de l'attraper si on avait affaire à quelque chose de moins banal que f(i=-1, i=-1).

davidf fournit également un exemple d'entrelacement des instructions très similaire à l'harmaline de l'.

Bien que chacun de harmaline, de supercat et davidf' exemples sont un peu artificiel, prises ensemble, elles servent encore de fournir une réelle raison pourquoi f(i=-1, i=-1) devrait être un comportement indéfini.

J'ai accepté harmaline de la réponse, car elle fait le meilleur travail de traiter l'ensemble des significations de pourquoi, même si Paul Draper de la réponse adressée le "pourquoi" de la portion de mieux.

d'autres réponses

JohnB souligne que, si l'on considère surcharge des opérateurs d'affectation (au lieu de simplement les scalaires), alors on peut avoir des problèmes ainsi.

  • Un scalaire objet est un objet de type scalaire. Voir 3.9/9: "de l'Arithmétique types (3.9.1), l'énumération des types, des types pointeur, pointeur de types de membres (3.9.2), std::nullptr_t, et de cv qualifiés versions de ces types (3.9.3) sont collectivement appelés types scalaires."
  • Peut-être il y a une erreur sur la page, et il s'agit f(i-1, i = -1) ou quelque chose de similaire.
  • Jetez un oeil à cette question: stackoverflow.com/a/4177063/71074
  • Merci. N' "arithmétique" types comprennent bool?
  • Eh bien, je suppose que la réponse est simple: l'ordre d'évaluation des paramètres dépend de la convention d'appel utilisé par le compilateur/architecture - qui le programmeur n'a pas beaucoup de contrôle(?!) et donc, le comportement peut être différent d'un compilateur/architecture à l'autre.
  • SchighSchagh votre mise à jour devrait être dans la section de réponse.
  • Vous devriez probablement mentionner dans le résumé, que, depuis le C++17 ce n'est pas UB plus, voir @AlexDs réponse

InformationsquelleAutor Nicu Stiurca | 2014-02-10