217 votes

Pourquoi cet énoncé if combinant une affectation et un contrôle d'égalité renvoie-t-il vrai ?

J'ai réfléchi à des erreurs de débutant et j'ai fini par choisir celle du if déclaration. J'ai étendu un peu le code à ceci :

int i = 0;
if (i = 1 && i == 0) {
    std::cout << i;
}

J'ai vu que le if retourne vrai, et il cout 's i comme 1 . Si i est attribué 1 dans l'instruction if, pourquoi i == 0 retourner true ?

83 votes

Les gars, ce n'est pas une question de typographie. L'OP veut savoir pourquoi l'instruction if est entrée avec ce code puisque i est réglé sur 1 .

25 votes

Ou assigne-t-il le résultat de 1 && i == 0 ?

4 votes

Suggestion pour les débutants : Ils ne devraient pas utiliser une telle construction linguistique "avancée". Il suffit d'assigner la variable séparément. Cela évitera également d'éventuels problèmes avec le point de séquence. Ce type de code dans le code pratique sera généralement mauvais aussi.

394voto

NathanOliver Points 10062

Cela a à voir avec la préséance des opérateurs .

if (i = 1 && i == 0)

n'est pas

if ((i = 1) && (i == 0))

parce que les deux && y == ont une priorité plus élevée que = . Ce qui revient à dire que

if (i = (1 && (i == 0)))

qui assigne le résultat de 1 && (i == 0) a i . Donc, si i commence à 0 puis i == 0 es true donc 1 && true es true (ou 1 ), et ensuite i est réglé sur 1 . Puisque 1 est vrai, vous entrez dans le bloc if et imprimez la valeur que vous avez assignée à i .

17voto

En supposant que votre code ressemble réellement à ceci :

#include <iostream>
using namespace std;

int main()  {
    int i = 0;
    if (i = 1 && i == 0) {
        cout << i;
    }
}

Puis ceci :

if (i = 1 && i == 0) {

est évalué comme

 if (i = (1 && i == 0)) {

et ainsi i est réglé sur 1 .

-3voto

ar18 Points 327

La réponse réelle est :

  1. Le compilateur donne préséance à "i == 0", qui vaut vrai.
  2. Il évaluera alors i=1 comme VRAI ou FAUX, et comme les opérateurs d'affectation compilés n'échouent jamais (sinon ils ne seraient pas compilés), il évalue également à vrai.
  3. Puisque les deux instructions sont évaluées comme vraies, et que VRAI && VRAI est évalué comme VRAI, l'instruction if sera évaluée comme VRAIE.

Pour le prouver, il suffit de regarder la sortie asm de votre compilateur pour le code que vous avez saisi (tous les commentaires sont les miens) :

mov     dword ptr [rbp - 8], 0    ; i = 0;
cmp     dword ptr [rbp - 8], 0    ; i == 0?
sete    al                        ; TRUE (=1)
mov     cl, al
and     cl, 1                     ; = operator always TRUE
movzx   edx, cl
mov     dword ptr [rbp - 8], edx  ; set i=TRUE;
test    al, 1                     ; al never changed,
                                  ; so final ans is TRUE

La sortie asm ci-dessus provient de CLANG, mais tous les autres compilateurs que j'ai examinés ont donné une sortie similaire. Ceci est vrai pour tous les compilateurs de ce site, qu'ils soient des compilateurs C ou C++ purs, tous sans aucun pragme pour changer le mode du compilateur (qui par défaut est C++ pour les compilateurs C++).

Notez que votre compilateur n'a pas réellement défini i=1, mais i=TRUE (ce qui signifie toute valeur entière non nulle de 32 bits). C'est parce que l'opérateur && évalue seulement si une déclaration est VRAIE ou FAUX, et définit ensuite les résultats en fonction de ce résultat. Pour le prouver, essayez de remplacer i=1 par i=2 et vous pourrez constater par vous-même que rien ne change. Constatez par vous-même en utilisant n'importe quel compilateur en ligne à Explorateur de compilateurs

-4voto

Leslie Satenstein Points 154

Cela a à voir avec l'analyse syntaxique et les règles de droite à gauche. Par exemple, y = x+5.
Toutes les sous-expressions sont pondérées en importance. Deux expressions d'importance égale sont évaluées de droite à gauche, . Le côté de l'expression && est évalué en premier, suivi de la LHS.

C'est logique pour moi.

1 votes

L'associativité ("règles de droite à gauche") n'a rien à voir avec cela. Il s'agit de la préséance ("importance"), et les opérateurs utilisés Ne le fais pas. ont la même préséance.

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