web-dev-qa-db-fra.com

Plusieurs conditions dans une boucle 'pour'

Je suis tombé sur ce morceau de code. J'utilise généralement '&&' ou '||' pour séparer plusieurs conditions dans une boucle for, mais ce code utilise des virgules pour le faire.

Étonnamment, si je change l'ordre des conditions, la sortie varie.

#include<stdio.h>

int main() {
    int i, j=2;

    for(i=0; j>=0,i<=5; i++)
    {
         printf("%d ", i+j);
         j--;
    }
    return 0;
}

Sortie = 2 2 2 2 2 2

#include<stdio.h>

int main(){
    int i, j=2;

    for(i=0; i<=5,j>=0; i++)
    {
         printf("%d ", i+j);
         j--;
    }
    return 0;
}

Sortie = 2 2 2

Quelqu'un peut-il expliquer la raison? Il semble ne vérifier que la dernière condition séparée par des virgules.

25
Prateek

L'opérateur par virgule évalue tous ses opérandes et renvoie la valeur du dernier. Donc, fondamentalement, quelle que soit la condition dans laquelle vous écrivez d’abord, il sera ignoré, et le deuxième un sera significatif uniquement.

for (i = 0; j >= 0, i <= 5; i++)

est donc équivalent avec

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

ce qui peut ou non correspondre à l'intention de l'auteur du code, en fonction de ses intentions - J'espère que ce n'est pas du code de production, car si le programmeur ayant écrit cela voulait exprimer une relation AND entre les conditions, alors il s'agit d'une erreur && opérateur aurait dû être utilisé à la place.

50
user529758

Bien sûr, ce que vous dites au début est correct, et C opérateur logique&& et || sont ce que vous utilisez habituellement pour "connecter" des conditions (expressions pouvant être évaluées comme vraies ou fausses); l'opérateur de virgule n'est pas un opérateur logique et son utilisation dans cet exemple n'a aucun sens, comme l'expliquent d'autres utilisateurs. Vous pouvez l’utiliser par exemple pour "concaténer" des instructions dans le pour lui-même: vous pouvez initialiser et mettre à jour j avec j; ou utilisez l'opérateur virgule de autrede manière

#include <stdio.h>

int main(void)  // as std wants
{
  int i, j;

  // init both i and j; condition, we suppose && is the "original"
  // intention; update i and j
  for(i=0, j=2; j>=0 && i<=5; i++, j--)
  {
       printf("%d ", i+j);
  }
  return 0;        
}
6
ShinTakezou

La virgule prend la valeur de l'expression last (par exemple, la plus à droite).

Donc, dans votre première boucle, la seule expression de contrôle est i<=5; et j>=0 est ignoré.

Dans la seconde boucle, j>=0 contrôle la boucle et i<=5 est ignoré.


En ce qui concerne une raison ... il n'y a aucune raison. Ce code est juste faux . La première partie des expressions de virgule ne fait rien sauf dérouter les programmeurs. Si un programmeur sérieux écrit cela, il devrait avoir honte d’eux-mêmes et voir son clavier révoqué.

5
abelenky

Ne pas utiliser ce code quiconque l'a écrit a clairement une incompréhension fondamentale de la langue et n'est pas digne de confiance. L'expression:

j >= 0, i <= 5

évalue "j> = 0", puis le jette et ne fait rien avec. Ensuite, il évalue "i <= 5" et utilise cela, et seulement cela, comme condition pour terminer la boucle. L'opérateur de virgule peut peut être utilisé de manière significative dans une condition de boucle lorsque l'opérande de gauche a des effets secondaires; vous verrez souvent des choses comme:

for (i = 0, j = 0; i < 10; ++i, ++j) . . .

dans lequel la virgule est utilisée pour insérer des instructions d'initialisation et d'incrémentation supplémentaires. Mais le code affiché ne fait pas cela, ni quoi que ce soit de significatif.

3

Wikipedia indique ce que fait l'opérateur de virgule:

"Dans les langages de programmation C et C++, l'opérateur de virgule (représenté par le jeton ,) est un opérateur binaire qui évalue son premier opérande et ignore le résultat, puis évalue le deuxième opérande et renvoie cette valeur (et ce type)."

3
tafa

Il existe un opérateur en C appelé opérateur virgule. Il exécute chaque expression dans l'ordre et renvoie la valeur de la dernière instruction. C'est également un séquence point , ce qui signifie que chaque expression est garantie de s'exécuter complètement et dans l'ordre avant que la prochaine expression de la série ne s'exécute, similaire à && ou ||

2
Robert S. Barnes

Pour compléter la réponse de M. Crocker, faites attention aux opérateurs ++ ou - ou je ne connais pas les autres opérateurs peut-être… .. Ils peuvent affecter la boucle. Par exemple, j'ai vu un code similaire à celui-ci dans un cours:

for(int i=0; i++*i<-1, i<3; printf(" %d", i));

Le résultat serait de 1 2 $. Ainsi, la première déclaration a affecté la boucle, alors que le résultat suivant est une multitude de zéros.

for(int i=0; i<3; printf(" %d", i));
0
MSN