La priorité de l'opérateur (et l'associativité) de l'état l'ordre dans lequel l'expression est interprétée et exécutée. Toutefois, cela ne dit rien sur l' ordre d'évaluation des opérandes, qui est un terme différent. Exemple:
a() + b() * c()
La priorité de l'opérateur dicte que le résultat de l' b()
et le résultat d' c()
doit être multipliée avant l'ajout de concert avec le résultat de l' a()
.
Cependant, il ne dit rien sur l'ordre dans lequel ces fonctions doivent être exécutées. L'ordre d'évaluation de chaque opérateur indique ce. Le plus souvent, l'ordre d'évaluation n'est pas spécifié (comportement non spécifié), ce qui signifie que la norme permet au compilateur de le faire dans n'importe quel ordre il aime. Le compilateur n'a pas besoin de document de la présente ordonnance ni ne doivent se comporter de manière cohérente. La raison pour cela est de donner des compilateurs plus de liberté dans l'expression de l'analyse, sens de l'accélération de la compilation et éventuellement aussi d'accélérer l'exécution du code.
Dans l'exemple ci-dessus, j'ai écrit un programme de test simple et mon compilateur exécuté les fonctions ci-dessus dans l'ordre a()
, b()
, c()
. Le fait que le programme doit s'exécuter à la fois b()
et c()
avant de pouvoir multiplier les résultats, ne veut pas dire qu'il faut évaluer ces opérandes dans une commande donnée.
C'est là que la séquence de points. C'est un point donné dans le programme où toutes les évaluations précédentes (et activités) doit être effectué. Si la séquence de points sont pour la plupart liés à la commande de l'évaluation et non pas la priorité de l'opérateur.
Dans l'exemple ci-dessus, les trois opérandes sont séquencé par rapport à l'autre, ce qui signifie qu'aucun point de séquence dicte l'ordre d'évaluation.
Par conséquent, il s'avère problématique lorsque les effets secondaires sont introduit dans séquencé expressions. Si nous écrivons i++ + i++ * i++
, alors que nous ne savons pas encore à l'ordre dans lequel ces opérandes sont évalués, de sorte que nous ne pouvons pas déterminer ce que sera le résultat. C'est parce que les deux +
et *
ont non spécifié/non séquencés afin de l'évaluation.
Avions-nous écrit, i++ || i++ && i++
, alors le comportement serait bien défini, parce que l' &&
et ||
spécifie l'ordre d'évaluation à gauche-à-droite et il y a un point de séquence entre l'évaluation de la gauche et de l'opérande de droite. Ainsi, if(i++ || i++ && i++)
est parfaitement portable et coffre-fort (même si illisible) du code.
Quant à l'expression i = i++;
, le problème ici est que l' =
est définie comme (6.5.16):
Les effets secondaires de la mise à jour de la valeur de l'opérande de gauche est séquencé après la valeur des calculs de la gauche et la droite opérandes. Les évaluations de la opérandes sont séquencé.
Cette expression est en fait proche d'être bien défini, car le texte dit que l'opérande de gauche ne doit pas être mis à jour avant de l'opérande de droite est calculée. Le problème, c'est la dernière phrase: l'ordre d'évaluation des opérandes est non spécifié/non.
Et puisque l'expression contient l'effet secondaire de l' i++
, il invoque un comportement indéfini, puisque nous ne pouvons pas savoir si l'opérande i
ou l'opérande i++
est évalué en premier.
(Il n'y a plus que ça, étant donné que la norme indique également qu'un opérande ne doit pas être utilisé deux fois dans une expression à des fins différentes fins, mais c'est une autre histoire.)