La Priorité de l'opérateur vs Ordre d'Évaluation

Les termes "la priorité de l'opérateur" et "l'ordre de l'évaluation" sont très couramment utilisés termes de programmation et c'est extrêmement important pour un programmeur de savoir. Et, comme je le comprends, les deux concepts sont étroitement liés; on ne peut pas faire sans l'autre quand on parle d'expressions.

Prenons un exemple simple:

int a=1;  //Line 1
a = a++ + ++a;  //Line 2
printf("%d",a);  //Line 3

Maintenant, il est évident que Line 2 conduit à un Comportement Indéfini, depuis Séquence de points en C et C++ comprennent:

  1. Entre l'évaluation de la gauche et de la droite des opérandes de l' && (logique
    ET), || (OU logique), et par des virgules
    des opérateurs. Par exemple, dans le
    expression *p++ != 0 && *q++ != 0, tous les
    effets secondaires de la sous-expression
    *p++ != 0 sont terminées avant toute tentative d'accès à q.

  2. Entre l'évaluation de la première opérande de l'ternaire
    "point d'interrogation" de l'opérateur et de l'
    deuxième ou troisième opérande. Par exemple,
    dans l'expression a = (*p++) ? (*p++)
    : 0
    il y a un point de séquence après
    la première *p++, sens qu'il a déjà
    été incrémenté par le temps de l'
    la deuxième instance est exécuté.

  3. À la fin d'une pleine expression. Cette catégorie comprend expression
    états (comme la cession
    a=b;), de retour des états, la
    le contrôle des expressions de if, switch,
    tout ou-même si des déclarations, et toutes les
    trois expressions dans une instruction for.

  4. Avant qu'une fonction est entré dans un appel de fonction. L'ordre dans lequel
    les arguments sont évalués n'est pas
    spécifié, mais ce point de séquence
    signifie que l'ensemble de leurs effets secondaires
    avant la fonction est
    entré. Dans l'expression f(i++) + g(j++) + h(k++),
    f est appelée avec un
    paramètre de la valeur d'origine de i,
    mais i est incrémenté avant d'entrer dans
    le corps de f. De même, j et k sont
    mis à jour avant d'entrer dans g et h
    respectivement. Cependant, il n'est pas
    spécifié dans quel ordre f(), g(), h()
    sont exécutées, ni dans quel ordre i, j,
    k sont incrémentés. Les valeurs de j et
    k dans le corps de f sont donc
    undefined.Trois Notez qu'une fonction
    appel f(a,b,c) n'est pas une utilisation de l'
    opérateur virgule et de l'ordre de
    évaluation pour a, b, et c est
    non spécifié.

  5. À un retour de la fonction, après le retour de la valeur est copiée dans le
    l'appel de contexte. (De ce point de séquence
    n'est spécifié dans la norme C++;
    elle n'est présente que de manière implicite dans
    C.)

  6. À la fin d'un initialiseur; par exemple, après l'évaluation de 5
    dans la déclaration int a = 5;.

Ainsi, passant par le Point n ° 3:

À la fin d'une pleine expression. Cette catégorie comprend l'expression des états (comme l'affectation a=b;), de retour des états, le contrôle des expressions de if, switch, while, ou le faire-même si des déclarations, et toutes les trois expressions dans une instruction for.

Line 2 clairement conduit à un Comportement Indéfini. Cela montre comment Comportement Indéfini est étroitement couplé avec Séquence de Points de.

Prenons maintenant un autre exemple:

int x=10,y=1,z=2; //Line 4
int result = x<y<z; //Line 5

Maintenant son évident que Line 5 fera la variable result magasin 1.

Maintenant l'expression x<y<z dans Line 5 peut être évalué comme:

x<(y<z) ou (x<y)<z. Dans le premier cas, la valeur de result sera 0 et dans le second cas result sera 1. Mais nous savons que, lorsque le Operator Precedence est Equal/Same - Associativity entre en jeu, donc, est évaluée comme (x<y)<z.

C'est ce qui est dit dans ce Article MSDN:

La priorité et associativité des opérateurs de C affectent le regroupement et l'évaluation des opérandes dans les expressions. Un opérateur de priorité n'a de sens que si d'autres opérateurs plus ou moins élevés de précédence sont présents. Expressions avec plus de précédence des opérateurs sont évalués en premier. La priorité peut aussi être décrit par le mot "contraignantes". Les opérateurs avec une priorité plus élevée sont dit d'avoir le resserrement de liaison.

Maintenant, à propos de l'article ci-dessus:

Il mentionne les "Expressions avec plus de précédence des opérateurs sont évalués en premier."

Il peut sembler incorrecte. Mais, je pense que l'article n'est pas de dire quelque chose de mal si l'on considère que () est également un opérateur x<y<z est la même que (x<y)<z. Mon raisonnement est que si l'associativité n'est en jeu, alors les expressions complètes évaluation devient ambigu car < n'est pas un Point de Séquence.

Aussi, un autre lien que j'ai trouvé dit cela à Priorité et Associativité des opérateurs:

Cette page répertorie les opérateurs de C dans l'ordre de priorité (de la plus haute à la plus basse). Leur associativité indique dans quel ordre les opérateurs de même priorité, dans une expression sont appliquées.

Donc, en prenant, le deuxième exemple de int result=x<y<z, nous pouvons voir ici qu'il y a en tout 3 expressions, x, y et z, depuis, la forme la plus simple d'une expression est composée d'une seule constante littérale ou d'un objet. Donc le résultat des expressions x, y, z serait là rvalues, c'est à dire, 10, 1 et 2 respectivement. Donc, maintenant nous pouvons interpréter x<y<z comme 10<1<2.

Maintenant, n'est-ce pas l'Associativité entrent en jeu depuis maintenant, nous avons 2 expressions à évaluer, soit 10<1 ou 1<2 et puisque la priorité de l'opérateur est même, ils sont évaluées de gauche à droite?

Prenant ce dernier exemple que mon argument:

int myval = ( printf("Operator\n"), printf("Precedence\n"), printf("vs\n"),
printf("Order of Evaluation\n") );

Maintenant dans l'exemple ci-dessus, depuis le comma opérateur a même ordre de priorité, les expressions sont évaluées left-to-right et la valeur de retour de la dernière printf() est stocké dans myval.

Dans DONC/IEC 9899:201x sous J. 1 comportement non spécifié il mentionne:

L'ordre dans lequel les sous-expressions sont évaluées et l'ordre dans lequel les effets secondaires
prendre place, sauf tel que spécifié pour la fonction call (), &&, ||, ?:, et la virgule
les opérateurs (6.5).

Maintenant je voudrais savoir, serait-il faux de dire:

Ordre de l'Évaluation dépend de la priorité des opérateurs, laissant les cas de Comportement non spécifié.

Je voudrais être corrigé si des erreurs ont été faits dans quelque chose je l'ai dit dans ma question.
La raison que j'ai posté cette question est en raison de la confusion créée dans mon esprit par l'Article MSDN. Est-il dans Erreur ou pas?

  • Je suis avec vous tout le chemin jusqu'à la conclusion, mais ne voyez pas où vous obtenez le comportement quelconque.
  • Comme je l'ai lu la norme, (x<y)<z ne fait que clarifier l'associativité/priorité. Les deux sous-expressions (x<y) et z pu être évalués dans l'ordre.
  • Persson:: La raison pour laquelle j'ai de l'etat un comportement non spécifié est parce que dans des situations comme:obj + obj++ le comportement est indéterminé, même si l'ordre de préséance est le même.
  • Je ne sais pas à propos de C++. Le C Norme ne définit pas une "priorité"; il définit une grammaire. La grammaire pour l'évaluation de l'expression impose un certain groupement de sous-expressions.
  • La priorité des opérateurs n'est pas spécifiée directement, mais elle peut être obtenue à partir de la syntaxe.
  • Précisément mon point de vue!! Donc, qui devrait MSDN article être considéré imparfait ou pas?
  • Dépend. Cette affirmation est peut-être vrai pour MSVC - mais ce n'est pas le cas pour le c++ en général, autant que je puisse en dire.
  • Le comportement de l'obj + obj++ n'est pas défini, pas juste non spécifié. C'est undefined, car la norme explicitement dit, mais la priorité n'a rien à voir avec la question.
  • Je voudrais savoir à partir d'un C Standard point de vue.
  • Aucune idée sur C. Pour C++, je suis pratiquement certaine que mon commentaire initial est correct.
  • Lire ma réponse. La priorité et associativité des règles de définir la forme de l'expression de l'arbre, et non pas l'ordre dans lequel il sera évalué.
  • Kanze:: Désolé, c'était une faute de frappe. je voulais dire ++obj + obj++obj est un objet de certains type de classe et où ++ est surchargé, d'où l'évaluation est indéterminé et semblable à f1() + f2(), .
  • La confusion est surgissent à cause de mon les commentaires ici.
  • Lire Jerry Cercueil de réponse. Il sera clairement de toutes vos confusions.
  • double possible de l'ordre d'évaluation des opérandes

InformationsquelleAutor Sadique | 2011-03-29