Pourquoi est-ce que «if (i ++ && (i == 1))» false où i est un int contenant la valeur 1?

{ int i = 1; if (i++ && (i == 1)) printf("Yes\n"); else printf("No\n"); } 

D’après ce que j’ai compris, dans la condition if , l’expression ( i==1 ) sera d’abord évaluée, ce qui devrait renvoyer 1 , puis logiquement avec 1 qui est la valeur de i , l’expression devrait donc renvoyer 1 && 1 == 1 , mais la partie else est exécutée.

Quelqu’un peut-il s’il vous plaît expliquer pourquoi l’ else partie est exécutée?

Non. En C, il y a un sharepoint séquence entre l’évaluation du LHS de l’opérateur && et l’évaluation du RHS, et l’incrément doit avoir lieu et être terminé avant l’évaluation du RHS. Donc, le i++ (équivalent à i++ != 0 ) est exécuté et l’incrément est terminé (et l’expression est évaluée à true), donc au moment où le RHS est évalué, i == 2 et donc l’expression globale est fausse et vous obtenir ‘Non’ imprimé. Si le LHS de l’opérateur && évalué à false (0), le RHS ne serait pas évalué en raison de la propriété de court-circuit de l’opérateur && .

Seuls quelques opérateurs ont la propriété d’avoir un sharepoint séquence entre l’évaluation du LHS et du RHS: && , || , et (en tant qu’opérateur, pas comme séparateur dans une liste d’arguments) – et il y a ? : ? : aussi, qui n’est pas un opérateur binary mais qui a un sharepoint séquence après l’évaluation de la condition et avant soit l’expression après le ? ou l’expression après le : est évaluée (dont l’une ou l’autre, mais pas les deux, est toujours évaluée).

Le && et || les opérateurs sont les seuls opérateurs à posséder la propriété “court-circuit”. Le RHS de && n’est évalué que si le LHS a la valeur true; l’ERS de || n’est évalué que si le LHS est évalué comme faux.


Clarification sur les points de séquence

Je n’existe pas Idonotexist a bien affirmé :

La norme C11 n’a pas supprimé les points de séquence, seule la norme C ++ 11 l’a fait.

C ++ 11 (ISO / IEC 14882: 2011) dit:

1.9 Exécution du programme

¶13 Le séquencement précédent est une relation asymésortingque, transitive et par paire entre les évaluations exécutées par un seul thread (1.10), qui induit un ordre partiel parmi ces évaluations. Compte tenu de deux évaluations A et B , si A est séquencé avant B , alors l’exécution de A doit précéder l’exécution de B. Si A n’est pas séquencé avant que B et B ne soient pas séquencés avant A , alors A et B ne sont pas séquencés . [ Remarque: L’exécution d’évaluations non séquencées peut se chevaucher. – note de fin ] Les évaluations A et B sont séquencées indéfiniment lorsque A est séquencé avant B ou B est séquencé avant A , mais il n’est pas spécifié lequel. [ Note: Les évaluations en séquence indéterminée ne peuvent pas se chevaucher, mais l’une ou l’autre peut être exécutée en premier. – note finale ]

Le terme «sharepoint séquence» n’apparaît pas du tout dans C ++ 11 (la seule correspondance proche est «pointeur de séquence»).

C11 (ISO / IEC 9899: 2011) dit:

5.1.2.3 Exécution du programme

¶3 La séquence précédente est une relation asymésortingque, transitive et par paires entre les évaluations exécutées par un seul thread, ce qui induit un ordre partiel parmi ces évaluations. Compte tenu de deux évaluations A et B , si A est séquencé avant B , alors l’exécution de A doit précéder l’exécution de B. (Inversement, si A est séquencé avant B , alors B est séquencé après A. ) Si A n’est pas séquencé avant ou après B , alors A et B ne sont pas séquencés . Les évaluations A et B sont séquencées indéfiniment lorsque A est séquencé avant ou après B , mais il n’est pas spécifié lequel. 13) La présence d’un sharepoint séquence entre l’évaluation des expressions A et B implique que chaque calcul de valeur et effet secondaire associé à A est séquencé avant chaque calcul de valeur et chaque effet secondaire associé à B. (Un résumé des points de séquence est donné en annexe C.)

13) Les exécutions d’évaluations non séquencées peuvent s’entrelacer. Les évaluations en séquence indéterminée ne peuvent pas être entrelacées, mais peuvent être exécutées dans n’importe quel ordre.

C11 conserve donc les points de séquence, mais ajoute les termes «séquencés avant» et connexes en utilisant essentiellement la même terminologie que C ++ 11.

Ici, une explication simple

entrer la description de l'image ici

et c’est pourquoi cette condition devient «fausse»

Lorsque && est utilisé dans une expression, ses arguments sont évalués de gauche à droite . Donc, i la valeur 2 quand (i==1) est évalué. Par conséquent, l’expression est fausse et la partie else sera exécutée.

Cependant, notez que si l’argument de gauche a la valeur false ou 0, le bon argument n’est pas du tout évalué.

Je pense que 1 && 1 = 1 et 1 && 0 = 0 est clair pour vous. La réponse de Michael L me semble bonne. Mais je vais quand même essayer de développer un peu. Voici le lien qui fournit la liste de priorité des opérateurs:

http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm

Si vous visitez ce lien et que vous vous référez à ce tableau, vous saurez alors que && a une associativité de gauche à droite.Alors je deviendrai 2 APRES partie gauche (Sruit a essayé de montrer ceci en utilisant un diagramme), puis pour la partie droite i == 1 vérification est faite. Nous pouvons vérifier cela en écrivant le code comme celui ci-dessous:

Ce code explique que i = 2 lorsque le stream d’exécution atteint i == 1 partie.

 #include  int main() { int i = 1; if (i++ && (printf("%d\n",i))) printf("Yes\n"); else printf("No\n"); return 0; } 

Donc, la sortie est la suivante:

2

Oui

Donc 2 == 1 se révèle faux et finalement la réponse donne un sentiment surprenant !!! Le support latéral droit donne 0 et le côté gauche 1 donc 1 && 0 = 0. Je pense que c’est assez juste pour comprendre.

Vous êtes confus parce que dans l’instruction en boucle, i ++ est utilisé pour l’incrémentation des postes. par exemple

 for (i=0;i<1;i++) 

Dans le programme de boucle ci-dessus, i vais d'abord obtenir la valeur initiale et vérifier la condition. La condition if est vraie, donc elle incrémente i et évalue i en ancienne valeur pour le corps de la boucle mais en dehors du corps de la boucle, elle a une nouvelle valeur 1 .

Dans votre question que vous utilisez if et la scope de l'ancienne valeur de i va se terminer quand il rencontre logiquement l'opérateur, il récupère automatiquement la nouvelle valeur et l'incrémente à 2 pour que la condition retourne faux.