Afin de vérifier les conditions dans C

0

La question

Donc, je lisais à propos de l'ordre des différents opérateurs, et j'ai lu que && est plus important que les || et il permettrait d'évaluer plus tôt (source). Ensuite, quelqu'un a posé une question au sujet de ce que ce morceau de code d'impression:

#include <stdio.h>
int main(){
    int a=0, b=0, c=0, d=0;
    if(a++>0 || ++b==1 || c--<=0 && d++>c--){
        printf("if\na:%d\nb:%d\nc:%d\nd:%d\n",a,b,c,d);
    }
    else{
        printf("else\na:%d\nb:%d\nc:%d\nd:%d\n",a,b,c,d);
    }
    return 0;
}

Et j'ai pensé que l' c-- <= 0 && d++ > c-- d'évaluer d'abord, ce qui est vrai dans l'ensemble. après le processus, c serait égale à -2 et d serait égal à 1. Ensuite, il serait de commencer à vérifier à partir de la gauche, de l'évaluation a++ > 0 || ++b == 1 ce qui est vrai, a 1 à la fin de la b est 1 dans la condition et après. de sorte que le total de l'état de true || true et il est vrai, de sorte que nous allons imprimer:

if
a:1
b:1
c:-2
d:1

Oui? Apparemment, non. Je l'ai testé avec GCC (Mingw) sur mon système (Windows 10), et avec un compilateur en ligne (cette une) et les deux imprimés:

if
a:1
b:1
c:0
d:0

J'ai changé la condition suivante: if(a++>0 || ++b==1 || (c--<=0 && d++>c--) ) mais le résultat est exactement la même chose sur les deux lieux. Il y a une chose que je ne fais pas attention? Ou est-ce quelque chose comme un bug? Il ressemble presque que || et && ont la même priorité et la chose entière est évaluée à partir de la gauche, et que le court-circuit se produit et d'autres choses. Si je change le ++b==1 la partie en ++b==0, alors la sortie est la même que j'avais prédit.
Merci d'avance pour toute aide :)

1

La meilleure réponse

4

L'expression de cette question:

if(a++>0 || ++b==1 || c--<=0 && d++>c--)

est un exemple classique d'un horrible, horrible expression, outrageusement irréaliste et impraticable, et punishingly difficile à comprendre, qui a pourtant fait un bon travail d'illustration d'un super point important: la priorité n'est pas le même que l'ordre d'évaluation.

Ce préséance vraiment nous dit, c'est la façon dont les opérateurs sont raccordés à leurs opérandes. Compte tenu de l'expression simplifiée

A || B || C && D

qui deux sous-expressions de faire le premier ||et la deuxième ||et la && en fait attacher et de les faire fonctionner sur? Si vous êtes un compilateur écrivain, vous répondez à ces questions par la construction d'un "arbre d'analyse", qui montre explicitement ce qui sous-expression(s) aller avec les opérateurs.

Donc, compte tenu de l'expression A || B || C && D, ne l'arbre d'analyse pour l'expression ressembler à ceci:

        &&
       /  \
     ||    D
    /  \
  ||    C
 /  \
A    B

ou comme ceci:

  ||
 /  \
A    ||
    /  \
   B    &&
       /  \
      C    D

ou comme ceci:

      ||
     /  \
    /    \
  ||      &&
 /  \    /  \
A    B  C    D

Pour répondre à cela, nous avons besoin de savoir non seulement que la priorité de && est plus élevé que ||mais aussi que || est-gauche associative. Compte tenu de ces faits, l'expression

A || B || C && D

est analysée comme si elle avait été écrite

(A || B) || (C && D)

et, par conséquent, les résultats de la troisième des trois candidat analyser les arbres je l'ai montré:

      ||
     /  \
    /    \
  ||      &&
 /  \    /  \
A    B  C    D

Mais maintenant nous sommes en mesure de vraiment voir comment le "court-circuiter" le comportement de l' || et && les opérateurs va être appliquée. Que "top" || va évaluer son côté gauche, et puis, si c'est faux, d'évaluer également le côté droit. De même, la baisse des || va évaluer son côté gauche. Donc, peu importe ce que, A va d'abord évaluée. Pour l'expression dans la question d'origine, qui correspond à a++ > 0.

Maintenant, a++>0 est fausse, donc nous allons avoir à évaluer Bqui est ++b == 1. Maintenant, c' est vrai, donc le résultat de la première || est "vrai".

Si le résultat de la seconde (en haut) || l'opérateur est aussi "vrai".

De sorte que le côté droit de la partie supérieure || l'opérateur n'a pas à être évaluées.

Donc, l'ensemble de la sous-expression contenant && ne seront pas évaluées.

Donc, même si && a la priorité la plus élevée, il a fini par être considéré comme le dernier, et, depuis que les choses à la gauche impliqués || et qui était vrai), il n'a pas de fin jusqu'à obtenir une évaluation à tous.

La ligne de fond, comme j'ai commencé par dire, c'est que la priorité n'est pas de déterminer l'ordre d'évaluation.

Aussi, si elle n'a pas été dit ailleurs, cette garantie, de gauche à droite comportement est seulement garanti pour la || et && les opérateurs (et, d'une manière différente, pour le ternaire ?: de l'opérateur). Si l'expression a été

A + B + C * D

il ne serait pas ont été vrai que, comme je l'ai dit plus tôt, "n'importe quoi, A va d'abord évaluée". Pour les opérateurs arithmétiques comme + et *, il n'y a aucun moyen de savoir si la gauche ou la droite va se faire d'abord évaluée.

2021-11-24 12:41:40

Complète et Rationnelle. Merci encore tellement.
III_phr

Dans d'autres langues

Cette page est dans d'autres langues

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................