Un comportement indéfini et de la séquence des points de
Que sont les "séquence de points"?
Quelle est la relation entre comportement indéfini et de la séquence des points?
J'utilise souvent drôle et alambiqué des expressions comme a[++i] = i;
, pour me sentir mieux. Pourquoi devrais-je cesser de les utiliser?
Si vous avez lu cela, assurez-vous de visiter la question de suivi Un comportement indéfini et de la séquence des points de reloaded.
(Note: Ceci est destiné à être une entrée à Un Débordement de pile du C++ FAQ. Si vous voulez une critique de l'idée de fournir une FAQ dans le présent formulaire, puis l'affichage sur des méta qui a commencé toute cette serait l'endroit pour le faire. Les réponses à cette question sont surveillés dans le C++ tchat, où la FAQ idée a commencé à en premier lieu, de sorte que votre réponse est très probablement le faire lire par ceux qui sont venus avec l'idée.)
OriginalL'auteur |
Vous devez vous connecter pour publier un commentaire.
C++98 et C++03
Cette réponse est pour les anciennes versions de la norme C++. Le C++11 et C++14 versions de la norme ne sont pas formellement contiennent la séquence de points; les opérations sont "séquencée avant" ou " non " ou "pour une période indéterminée séquencé" à la place. L'effet net est essentiellement le même, mais la terminologie est différente.
Avertissement : D'Accord. Cette réponse est un peu longue. Donc, avoir de la patience lors de la lecture. Si vous connaissez déjà ces choses, de les lire à nouveau ne sera pas vous rendre fou.
Pré-requis : Une connaissance élémentaire de la C++ Standard
Ce sont de Séquence de Points?
Que dit la Norme
Effets secondaires? Quels sont les effets secondaires?
Évaluation d'une expression produit quelque chose et si en plus il y a un changement dans l'état de l'environnement d'exécution, il est dit que l'expression (évaluation) a des effets secondaires(s).
Par exemple:
En plus de l'opération d'initialisation de la valeur des
y
est changé en raison de l'effet secondaire de++
de l'opérateur.So far So good. De passer à la séquence de points. Une alternance définition du seq-points donnés par la comp.lang.c auteur
Steve Summit
:Ce sont la séquence commune les points énumérés dans la Norme C++?
Ceux-ci sont:
§1.9/16
) (Une-expression est une expression qui n'est pas une sous-expression d'une autre expression.)1Exemple :
dans l'évaluation de chacune des expressions suivantes après l'évaluation de la première expression(
§1.9/18
) 2a && b (§5.14)
a || b (§5.15)
a ? b : c (§5.16)
a , b (§5.18)
(ici a , b est un opérateur virgule; dansfunc(a,a++)
,
n'est pas un opérateur virgule, c'est simplement un séparateur entre les argumentsa
eta++
. Ainsi, le comportement est indéfini dans ce cas (sia
est considéré comme un type primitif))à un appel de fonction (que ce soit ou non la fonction est en ligne), après l'évaluation de tous les arguments de la fonction (le cas échéant)
a lieu avant l'exécution de toutes les expressions ou des énoncés dans le corps de la fonction (
§1.9/17
).1 : Note : l'évaluation d'une expression peut inclure l'évaluation des sous-expressions qui ne sont pas lexicalement
la partie de l'expression. Par exemple, les sous-expressions participé à l'évaluation de l'argument par défaut des expressions (8.3.6) sont considérés comme être créé dans l'expression qui appelle la fonction, et non pas l'expression qui définit la valeur par défaut de l'argument
2 : Les opérateurs indiqués sont intégrés dans les opérateurs, comme décrit dans la clause 5. Lorsque l'un de ces opérateurs est en surcharge (clause 13) dans un contexte valide, donc la désignation d'un opérateur défini par l'utilisateur de la fonction, l'expression désigne une invocation de la fonction et les opérandes forme d'une liste d'arguments, sans implicite de point de séquence entre eux.
Ce qui est un Comportement indéterminé?
La Norme définit un Comportement indéterminé dans la Section
§1.3.12
comme3 : intensité admissible comportement indéfini plages d'ignorer la situation complètement avec des résultats imprévisibles, à se comporter lors de la traduction ou de l'exécution du programme dans documenté de façon caractéristique de l'environnement (avec ou avec
à l'émission d'un message de diagnostic), à la terminaison d'une traduction ou d'exécution (avec l'émission d'un message de diagnostic).
En bref, un comportement indéterminé signifie rien peut se produire à partir de démons volant de votre nez à votre petite amie était enceinte.
Quelle est la relation entre Comportement Indéfini et de la Séquence des Points?
Avant d'entrer dans que vous devez connaître la différence(s) entre Comportement indéfini, Indéterminé de Comportement et de mise en Œuvre de Comportement Défini.
Vous devez également savoir que
the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified
.Par exemple:
Un autre exemple ici.
Maintenant la Norme dans
§5/4
ditÇa veut dire quoi?
De manière informelle, ce qui signifie qu'entre deux séquences de points d'une variable ne doit pas être modifié plus d'une fois.
Dans une expression instruction, le
next sequence point
est généralement au point virgule, et leprevious sequence point
est à la fin de l'instruction précédente. Une expression peut également contenir des intermédiairessequence points
.De la phrase ci-dessus, les expressions suivantes invoquer un Comportement indéterminé:
Mais les expressions suivantes:
Ça veut dire quoi? Cela signifie que si un objet est écrit à l'intérieur d'une expression pleine de tout et de tous les accès à l'intérieur de la même expression doivent être directement impliqués dans le calcul de la valeur à écrire.
Par exemple dans
i = i + 1
tous les accès dei
(L. H. S et R. H. S) sont directement impliqués dans le calcul de la valeur à écrire. Donc, il est très bien.Cette règle limite l'expression juridique de celles dans lesquelles l'accès manifestement précéder la modification.
Exemple 1:
Exemple 2:
est rejetée parce que l'un des accès de
i
(l'un ena[i]
) n'a rien à voir avec la valeur qui est stockée dans i (ce qui arrive de plus eni++
), et donc il n'y a pas de bonne façon de définir--soit pour notre compréhension ou le compilateur--si l'accès doit avoir lieu avant ou après la valeur incrémentée est stocké. Ainsi, le comportement est indéfini.Exemple 3 :
Suivi de la réponse de C++11 ici.
*p++ = 4
n'est pas un Comportement indéterminé .*p++
est interprété comme*(p++)
.p++
retournep
(une copie) et la valeur stockée à l'adresse précédente. Pourquoi cela devrait-il invoquer l'UB? Il est parfaitement bien.Autant que je sache, il n'y a pas (juridique) des copies de la Norme C++ vous pouvez lier à.
Eh bien, alors vous pourriez avoir un lien vers l'ISO pertinentes de la page de commande. De toute façon, en pensant à elle, l'expression "connaissance élémentaire de la Norme C++" semble être un peu une contradiction dans les termes, car si vous êtes en train de lire le standard, vous avez passé le niveau élémentaire. Peut-être que nous avons pu dresser une liste de ce que les choses dans la langue vous avez besoin d'une compréhension de base, comme la syntaxe de l'expression, ordre des opérations, et peut-être la surcharge d'opérateur?
Je ne suis pas sûr de citant le standard est la meilleure façon d'enseigner aux débutants
La première expression appelle une UB, car il n'y a pas de point de séquence entre le dernier
++i
et l'assignement ài
. La seconde expression n'invoque pas UB parce que l'expressioni
ne change pas la valeur dei
. Dans le deuxième exemple, lei++
est suivie par une séquence de point (,
) avant que l'opérateur d'affectation est appelé.OriginalL'auteur
C'est un suivi à mon réponse précédente et contient du C++11..
Pré-requis : Une connaissance élémentaire de Relations (Mathématiques).
Est-il vrai qu'il n'y a pas de Séquence de Points de C++11?
Oui! Ce est très vrai.
Séquence de Points de ont été remplacés par des Séquencée Avant de et Séquencés Après (et Non et pour une période Indéterminée Séquencé) les relations en C++11.
Quelle est exactement cette "Séquencée avant de' chose?
Séquencée Avant de(§1.9/13) est une relation qui est:
entre les évaluations exécutées par un seul fil et induit une strict ordre partiel1
Formelle de moyens donnés deux évaluations(Voir ci-dessous)
A
etB
, siA
est séquencée avant deB
, puis l'exécution de l'A
doit précéder l'exécution deB
. SiA
n'est pas séquencée avant deB
etB
n'est pas séquencée avant deA
, puisA
etB
sont non 2.Évaluations
A
etB
sont pour une période indéterminée séquencé lorsqueA
est séquencée avant deB
ouB
est séquencée avant deA
, mais il n'est pas spécifié3.[NOTES]
1 : d'Un strict ordre partiel est un relation binaire
"<"
sur un ensembleP
qui estasymétrique
, ettransitive
, c'est à dire, pour tous lesa
,b
, etc
dansP
, nous avons que:........(j'). si a < b puis de b < a) (
asymmetry
);........(ii). si a < b et b < c puis a < c (
transitivity
).2 : L'exécution de séquencé évaluations peut chevauchement.
3 : pour une période Indéterminée séquencé évaluations ne peut pas chevauchement, mais qui pourrait être exécuté en premier.
Quel est le sens du mot "évaluation" dans le contexte de C++11?
En C++11, l'évaluation d'une expression (ou une sous-expression) comprend en règle générale:
valeur de calculs (y compris la détermination de l'identité d'un objet pour glvalue évaluation et récupérer une valeur précédemment affecté à un objet pour prvalue évaluation) et
initiation de effets secondaires.
Maintenant (§1.9/14) dit:
Exemple Trivial:
int x;
x = 10;
++x;
Valeur de calcul et des effets secondaires associés avec
++x
est séquencé après la valeur de calcul et des effets secondaires dex = 10;
Donc il doit y avoir une relation entre un Comportement indéterminé et le mentionnés ci-dessus des choses, non?
Oui! La droite.
(§1.9/15) il a été mentionné que
Par exemple :
+
opérateur sont séquencé les uns par rapport aux autres.<<
et>>
opérateurs sont séquencé les uns par rapport aux autres.4: Dans une expression qui est évaluée à plus d'une fois au cours de l'exécution
d'un programme, non et pour une période indéterminée séquencé des évaluations de ses sous-expressions ne doivent pas être exécutées de façon cohérente dans les différentes évaluations.
Cela signifie que dans
x + y
la valeur de calcul dex
ety
sont séquencée avant de la valeur de calcul de(x + y)
.Plus important
Exemples:
i = i++ * ++i; //Undefined Behaviour
i = ++i + i++; //Undefined Behaviour
i = ++i + ++i; //Undefined Behaviour
i = v[i++]; //Undefined Behaviour
i = v[++i]: //Well-defined Behavior
i = i++ + 1; //Undefined Behaviour
i = ++i + 1; //Well-defined Behaviour
++++i; //Well-defined Behaviour
f(i = -1, i = -1); //Undefined Behaviour (see below)
Expressions
(5)
,(7)
et(8)
ne pas se prévaloir d'un comportement indéterminé. Découvrez les réponses suivantes pour une explication plus détaillée.Note Finale :
Si vous trouvez une faille dans le poste, merci de laisser un commentaire. Utilisateurs (Avec rep >20000) n'hésitez pas à éditer le post pour corriger les fautes de frappe et autres erreurs.
Pourquoi est-7) de l'élément dans le dernier exemple, l'UB? Peut-être qu'il devrait être
f(i = -1, i = 1)
?Ici est la bonne explication: stackoverflow.com/a/21671069
J'ai corrigé la description de la "séquencée avant de" relation. C'est un le strict ordre partiel. De toute évidence, une expression ne peut pas être séquencée avant de lui-même, de sorte que la relation ne peut pas être réflexive. Par conséquent, il est asymétrique et non anti-symétrique.
5) bien befined a soufflé mon esprit. l'explication par Johannes Schaub n'était pas tout à fait simple à obtenir. Et surtout parce que j'estime que, même dans
++i
(valeur évaluée avant la+
de l'opérateur qui l'utilise), la norme ne peut toujours pas dire que son effet secondaire doit être fini. Mais en fait, parce qu'elle renvoie une ref à unlvalue
qui esti
lui-même, il DOIT avoir fini le côté effet depuis l'évaluation doit être fini, par conséquent, la valeur doit être à jour. C'était la partie folle pour obtenir en fait.OriginalL'auteur
C++17 (
N4659
) comprend une proposition Le raffinage de l'Évaluation de l'Expression de l'Ordre pour Idiomatiques C++ce qui définit le plus strict de l'ordre de l'évaluation de l'expression.
En particulier, la phrase suivante a été ajouté:
Il fait plusieurs cas déjà un comportement indéfini valide, y compris celui en question:
Cependant, plusieurs autres cas similaires, toujours conduire à un comportement indéfini.
Dans
N4140
:Mais dans
N4659
Bien sûr, à l'aide d'un C++17 conformes compilateur ne veut pas nécessairement dire que l'on devrait commencer à écrire de telles expressions.
OriginalL'auteur
Je devine il y a une raison fondamentale pour le changement, il n'est pas seulement cosmétique afin de rendre l'ancienne interprétation plus claire: que la raison est la simultanéité. Non spécifié afin d'élaboration, est simplement la sélection de l'une des nombreuses possibilités de série de rangements, c'est assez différent d'avant et après les achats, car si il n'est pas spécifié, la commande simultanée de l'évaluation est possible: pas avec les anciennes règles. Par exemple dans:
auparavant soit a, puis b, ou b puis un. Maintenant, a et b peuvent être évalués avec des instructions entrelacés ou même sur les différents cœurs.
OriginalL'auteur
Dans
C99(ISO/IEC 9899:TC3)
qui semble absent de ce débat donc loin de ce qui suit steteents sont faites au sujet de l'ordre de evaluaiton.OriginalL'auteur