59 votes

Quelle est la syntaxe complète de la boucle "for" en C ?

J'ai vu des choses très bizarres for boucles en lisant le code d'autres personnes. J'ai essayé de trouver une explication complète de la syntaxe de l'option for boucle en C mais c'est très difficile car le mot "for" apparaît dans des phrases sans rapport entre elles, ce qui rend la recherche presque impossible à effectuer efficacement.

Cette question m'est venue à l'esprit après avoir lu ce fil ce qui m'a rendu à nouveau curieux.

Le site for ici :

for(p=0;p+=(a&1)*b,a!=1;a>>=1,b<<=1);

Dans la condition du milieu, il y a une virgule qui sépare les deux morceaux de code, à quoi sert cette virgule ? La virgule du côté droit, je la comprends car elle fait que les deux parties du code sont séparées par une virgule. a>>=1 et b<<=1 .

Mais dans une condition de sortie de boucle, que se passe-t-il ? Est-ce qu'elle sort quand p==0 quand a==1 ou quand les deux se produisent ?

Ce serait formidable si quelqu'un pouvait m'aider à comprendre ce problème et peut-être m'indiquer la direction d'un système complet de gestion de l'eau. for description de la syntaxe de la boucle.

0 votes

@Jesus -- Tu as corrigé "kinda" en "kind of", "coma" en "virgule", mis une majuscule à "I" et "Does" mais laissé "ppl" pour "people" ?

0 votes

J'ai corrigé quelques erreurs. Le message est beaucoup mieux présenté maintenant. Question intéressante.

130voto

CesarB Points 18048

La virgule n'est pas exclusive des boucles for ; c'est l'opérateur virgule.

x = (a, b);

fera d'abord a, puis b, puis fixera x à la valeur de b.

La syntaxe de for est :

for (init; condition; increment)
    ...

Ce qui est un peu (en ignorant continue et break pour l'instant) équivalent :

init;
while (condition) {
    ...
    increment;
}

Donc votre exemple de boucle for est (encore une fois en ignorant continue et break ) équivalent à

p=0;
while (p+=(a&1)*b,a!=1) {
    ...
    a>>=1,b<<=1;
}

Qui agit comme s'il était (encore une fois ignorant continue et break ) :

p=0; 
while (true) {
    p+=(a&1)*b;
    if (a == 1) break;
    ...
    a>>=1;
    b<<=1;
}

Deux détails supplémentaires de la boucle for qui n'étaient pas dans la conversion simplifiée en boucle while ci-dessus :

  • Si la condition est omise, elle est toujours true (ce qui entraîne une boucle infinie, à moins qu'un break , goto ou quelque chose d'autre interrompt la boucle).
  • A continue agit comme s'il s'agissait d'un goto vers un label juste avant l'incrément, contrairement à un continue dans la boucle while, ce qui permettrait de sauter l'incrément.

De plus, un détail important concernant l'opérateur virgule : c'est un point de séquence, comme && et || (c'est pourquoi je peux le diviser en déclarations séparées et garder son sens intact).


Changements dans C99

La norme C99 introduit quelques nuances non mentionnées plus haut dans cette explication (ce qui est très bien pour C89/C90).

Tout d'abord, toutes les boucles sont des blocs à part entière. Effectivement,

for (...) { ... }

est lui-même enveloppé dans une paire d'accolades

{
for (...) { ... }
}

La norme dit :

ISO/IEC 9899:1999 §6.8.5 Déclarations d'itération

¶5 Une déclaration d'itération est un bloc dont la portée est un sous-ensemble strict de la portée de son bloc qui l'entoure. Le corps de la boucle est également un bloc dont la portée est un sous-ensemble strict de la portée de l'instruction d'itération. de l'instruction d'itération.

Ceci est également décrit dans la justification en termes d'accolades supplémentaires.

Deuxièmement, le init en C99 peut être une déclaration (unique), comme dans

for (int i = 0; i < sizeof(something); i++) { ... }

Maintenant, le "bloc entourant la boucle" prend tout son sens ; il explique pourquoi la variable i ne sont pas accessibles en dehors de la boucle. Vous pouvez déclarer plus d'une variable, mais elles doivent toutes être du même type :

for (int i = 0, j = sizeof(something); i < j; i++, j--) { ... }

La norme dit :

ISO/IEC 9899:1999 §6.8.5.3 L'instruction for

La déclaration

for ( clause-1 ; expression-2 ; expression-3 ) statement

se comporte comme suit : L'expression expression-2 est l'expression de contrôle qui est évaluée avant chaque exécution du corps de la boucle. L'expression expression-3 est évaluée comme une expression vide après chaque exécution du corps de la boucle. Si la clause-1 est une déclaration déclaration, la portée de toute variable qu'elle déclare est le reste de la déclaration et la totalité de la boucle, y compris les deux autres. la boucle entière, y compris les deux autres expressions ; elle est atteinte dans l'ordre d'exécution avant la première évaluation de l'expression de contrôle. Si la clause-1 est une expression, elle est évaluée comme une expression vide avant la première évaluation de l'expression de contrôle. 133)

La clause-1 et l'expression-3 peuvent être omises. Une expression-2 omise est remplacée par une constante non nulle.

133) Ainsi, la clause-1 spécifie l'initialisation de la boucle, en déclarant éventuellement une ou plusieurs variables à utiliser dans la boucle ; l'expression de contrôle, expression-2, spécifie une évaluation effectuée avant chaque itération, de sorte que l'exécution de la boucle se poursuit jusqu'à ce que l'expression soit égale à 0 ; et l'expression-3 spécifie une opération (telle que l'incrémentation) qui est effectuée après chaque itération.

0 votes

En C, la virgule a une priorité inférieure à l'affectation, donc "x = a, b ;" donnera d'abord à x la valeur a, puis fera b.

0 votes

@DavidThornley et si cela avait été x = a, b ; plutôt que (a, b) ?

0 votes

@TM : si j'ai bien compris, "x = a, b" va affecter a à x, puis évaluer b et rejeter sa valeur.

11voto

Le C++ permet de surcharger l'opérateur virgule. Sérieusement.

8voto

Konrad Rudolph Points 231505

La virgule sépare simplement deux expressions et est valable partout dans C où une expression normale est autorisée. Celles-ci sont exécutées dans l'ordre de gauche à droite. La valeur de l'expression la plus à droite est la valeur de l'expression globale.

for Les boucles sont constituées de trois parties, dont chacune peut également être vide ; une (la première) est exécutée au début, et une (la troisième) à la fin de chaque itération. En général, ces parties initialisent et incrémentent un compteur, respectivement ; mais elles peuvent faire n'importe quoi.

La deuxième partie est un test qui est exécuté au début de chaque exécution. Si le test donne false la boucle est interrompue. C'est tout ce qu'il y a à faire.

4 votes

La façon dont vous avez formulé votre phrase "un (le premier) est exécuté au début, et un (le troisième) à la fin de chaque itération" pourrait amener certaines personnes à penser que la première partie est exécutée au début de chaque itération.

5voto

Tomalak Points 150423

La boucle for de style C se compose de trois expressions :

for (initializer; condition; counter) statement_or_statement_block;
  • L'initialisateur s'exécute une fois, lorsque la boucle démarre.
  • La condition est vérifiée avant chaque itération. La boucle s'exécute tant que la condition est évaluée à true.
  • Le compteur est exécuté une fois après chaque itération.

Chacune de ces parties peut être une expression valide dans le langage dans lequel vous écrivez la boucle. Cela signifie qu'elles peuvent être utilisées de manière plus créative. Tout ce que vous voulez faire avant peut aller dans l'initialisateur, tout ce que vous voulez faire entre les deux peut aller dans la condition ou le compteur, jusqu'au point où la boucle n'a plus de corps.

Pour ce faire, l'opérateur virgule est très utile. Il vous permet de chaîner des expressions entre elles pour former une nouvelle expression unique. La plupart du temps, il est utilisé de cette manière dans une boucle for, les autres implications de l'opérateur virgule (par exemple, les considérations relatives à l'affectation de valeurs) jouant un rôle mineur.

Même si l'on peut faire des choses intelligentes en utilisant la syntaxe de manière créative, je m'en tiendrais à l'écart jusqu'à ce que je trouve une vraiment une bonne raison de le faire. Jouer au golf avec des boucles for rend le code plus difficile à lire et à comprendre (et à maintenir).

La wikipedia a une belle article sur la boucle for également.

0 votes

Est un autre for boucle autorisée dans le counter qui permettrait de définir des boucles for imbriquées dans la même déclaration ? En d'autres termes, comment une boucle for composée est-elle définie en C/C++ ?

0 votes

Je ne suis pas assez calé en langage C pour répondre à cette question. Néanmoins, la question est intéressante et originale. Il y a de bonnes chances d'obtenir une réponse si vous la posez comme une vraie question ici.

1 votes

Et j'ai suivi votre conseil, voici un réponse . Et s'il vous plaît upvote la question si vous le souhaitez. Bonne lecture !

2voto

Tout est facultatif dans un for boucle. Nous pouvons initialiser plus d'une variable, nous pouvons vérifier plus d'une condition, nous pouvons itérer plus d'une variable en utilisant l'opérateur virgule.

Les éléments suivants for vous entraînera dans une boucle infinie. Faites attention en vérifiant la condition.

for(;;)

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