31 votes

L'ordre des opérations change-t-il dans une expression if?

Je suis récemment tombé sur quelque chose que je pensais que je l'ai compris dès le départ, mais la réflexion plus sur lui, je voudrais comprendre pourquoi il fonctionne de la manière qu'il le fait.

Considérez le code ci-dessous. L' (x-- == 9) est clairement d'obtenir une évaluation, tandis que l' (y++ == 11) ne l'est pas. Ma première pensée était que logique, && coups de pied dans, voit que l'expression est déjà devenu faux, et des coups de pied avant de l'évaluation de la deuxième partie de l'expression.

Plus j'y pense, plus je ne comprends pas pourquoi il se comporte comme il le fait. Ce que je comprends, les opérateurs logiques tomber en dessous de incrémenter les opérations dans l'ordre de préséance. Ne devrait pas (y++ == 11) être évalué, même si l'expression globale est déjà devenu faux?

En d'autres termes, ne faut-il pas l'ordre des opérations qui dictent (y++ == 11) être évalué avant l' if déclaration se rend compte de l'expression dans son ensemble sera faux?

#include <iostream>
using namespace std;

int main( int argc, char** argv )
{
    int x = 10;
    int y = 10;

    if( (x-- == 9) && (y++ == 11) )
    {
        cout << "I better not get here!" << endl;
    }

    cout << "Final X: " << x << endl;
    cout << "Final Y: " << y << endl;
    return 0;
}

Sortie:

Final X: 9
Final Y: 10

49voto

Steve Jessop Points 166970

opérateurs logiques tomber en dessous de incrémenter les opérations dans l'ordre de la préséance.

L'ordre de préséance est pas de l'ordre d'exécution. Ils sont complètement différents concepts. L'ordre de préséance n'affecte que l'ordre d'exécution dans la mesure où les opérandes sont évalués avant leur opérateur, et ordre de priorité permet de vous dire ce que les opérandes sont de chaque opérateur.

Court-circuiter les opérateurs sont une exception partielle, même à la règle que les opérandes sont évalués avant l'exploitant, puisqu'ils permettent d'évaluer la LHS, alors l'opérateur a son mot à dire si ou de ne pas évaluer les RHS, peut-être le membre de droite est évaluée, puis le résultat de l'opérateur est calculé.

Ne pensez pas que plus la priorité des opérations d'exécution de la première". Penser à eux "liaison serré". ++ a une priorité plus élevée que &&, et dans l'expression x ++ && y ++, la priorité de l'opérateur signifie que l' ++ "se lie plus étroitement à" y que && t, et donc l'expression globale est équivalent à (x++) && (y++), pas (x++ && y) ++.

45voto

James McNellis Points 193607

Ne devrait pas (y++ == 11) être évalué, même si l'expression globale est déjà devenue false?

Non: l' && et || opérateurs de court-circuit: ils sont évalués de gauche à droite et dès que le résultat de l'expression est connue, l'évaluation s'arrête (c'est, dès que l'expression est connue pour être false dans le cas d'une série d' &&ou true dans le cas d'une série d' ||)(*).

Il n'y a pas de sens dans ce travail supplémentaire qui n'a pas besoin d'être fait. Ce court-circuit comportement est également très utile et permet l'écriture de terser code. Par exemple, un pointeur vers une struct type d'objet, vous pouvez tester si le pointeur est null et puis déréférencer le pointeur dans un sous-expression, par exemple: if (p && p->is_set) { /* ... */ }.


(*) Note qu'en C++, vous pouvez surcharger la fois l' && et de la || pour la classe-type des opérandes et si vous le faites, ils perdent leur court-circuit de la propriété (il est généralement déconseillé de surcharger && et || pour cette raison).

13voto

caf Points 114951

La priorité et l'associativité de ne pas spécifier l'ordre dans lequel les opérations sont effectivement réalisées. Ils spécifient la manière dont les opérations sont regroupées: c'est, dans l'expression suivante:

x && y++

...la priorité inférieure de l' && dit que c'est regroupées comme si c'était:

x && (y++)

plutôt que de

(x && y)++

Dans votre expression, la priorité relative de && et ++ n'ont pas d'importance, parce que vous avez séparée de ces opérateurs avec des parenthèses de toute façon.

Groupement (et, par conséquent, la priorité et l'associativité) spécifier quelle valeur de chaque opérateur d'exploitation; mais il précise rien à ce sujet quand il le fait.

Pour la plupart des opérateurs, l'ordre dans lequel les opérations sont effectuées est indéterminé - toutefois, dans le cas d' && il est précisé à évaluer l'opérande de gauche d'abord, puis seulement d'évaluer la droite opérande si le résultat de l'opérande de gauche est non nulle.

7voto

Chris Jester-Young Points 102876

Pas de. L'ordre de préséance décide tout simplement de savoir si vous obtenez ceci:

A && B

(avec A être x-- == 9 et B être y++ == 11) ou

A == B == C

(avec A être x--, B être 9 && y++, et C étant de 11).

Évidemment, nous sommes face à la première affaire. Le court-circuit s'applique pleinement; si A est vrai, alors B n'est pas évalué.

1voto

nightcracker Points 34498

Les opérateurs conditionnels évaluent la gauche vers la droite et s'arrêtent dès que le résultat est connu (un AND avec une falsité ou un OR avec une valeur vraie).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X