Quelle est la syntaxe complète de la boucle «for» en C (et d’autres si elles sont compatibles)?

J’ai vu des boucles très étranges lors de la lecture du code d’autres personnes. J’ai essayé de chercher une explication de la syntaxe complète de la boucle for dans C mais c’est très difficile parce que le mot ” for ” apparaît dans des phrases sans rapport rendant la recherche presque impossible pour Google efficacement.

Cette question me vint à l’esprit après avoir lu ce fil qui me rendait curieux à nouveau.

Le for ici:

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

Au milieu, il y a une virgule séparant les deux morceaux de code, que fait cette virgule? Je comprends la virgule à droite car cela fait à la fois a>>=1 et b<<=1 .

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

Ce serait génial si quelqu’un pouvait m’aider à comprendre cela et à me diriger vers une description complète for syntaxe de la boucle.

La virgule ne comprend pas les boucles for; c’est l’opérateur de virgule.

 x = (a, b); 

fera d’abord a, puis b, puis définira x à la valeur de b.

La syntaxe for est:

 for (init; condition; increment) ... 

Ce qui est un peu (en ignorant continue et break pour le moment) équivalent à:

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

Donc, votre exemple de boucle 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 si c'était (encore une fois en 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 une boucle while ci-dessus:

  • Si la condition est omise, elle est toujours true (résultant en une boucle infinie à moins qu'une break , un goto ou autre chose ne brise la boucle).
  • Un continue agit comme si c'était un goto à une étiquette juste avant l'incrément, contrairement à un continue dans la boucle while qui ignorerait l'incrément.

En outre, un détail important sur l'opérateur de virgule: c'est un sharepoint séquence, comme && et || (c'est pourquoi je peux le diviser en plusieurs déclarations et garder son sens intact).


Changements dans C99

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

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

 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 instruction d'itération est un bloc dont la scope est un sous-ensemble ssortingct de la scope de son bloc englobant. Le corps de la boucle est également un bloc dont la scope est un sous-ensemble ssortingct de la scope de l'instruction d'itération.

Ceci est également décrit dans la justification en termes de l'ensemble supplémentaire d'accolades.

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

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

Maintenant, le "bloc enveloppé autour de la boucle" prend tout son sens. cela explique pourquoi la variable i n'est pas accessible 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 La déclaration

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 é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, la scope des variables qu'elle déclare est le rest de la déclaration et la boucle entière, y compris les deux autres expressions; il est atteint 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)

Les clauses 1 et 3 peuvent être omises. Une expression omise-2 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 continue jusqu'à ce que l'expression soit égale à 0; et expression-3 spécifie une opération (telle que l'incrémentation) qui est effectuée après chaque itération.

La virgule sépare simplement deux expressions et est valide n’importe où dans C où une expression normale est autorisée. Ceux-ci sont exécutés dans l’ordre de gauche à droite. La valeur de l’expression la plus à droite est la valeur de l’expression globale.

for boucles se composent de trois parties, dont chacune peut aussi être vide; une (la première) est exécutée au début et une (la troisième) à la fin de chaque itération. Ces parties initialisent généralement et incrémentent un compteur, respectivement; mais ils 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 produit un résultat false , la boucle est annulée. C’est tout ce qu’on peut en dire.

Le style C pour la boucle se compose de trois expressions:

 for (initializer; condition; counter) statement_or_statement_block; 
  • L’initialiseur s’exécute une fois, au démarrage de la boucle.
  • La condition est vérifiée avant chaque itération. La boucle s’exécute aussi longtemps qu’elle est évaluée à true.
  • Le compteur s’exécute une fois après chaque itération.

Chacune de ces parties peut être une expression valide dans la langue dans laquelle 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’initialiseur, tout ce que vous voulez faire entre les deux peut aller dans la condition ou le compteur, jusqu’à ce que la boucle n’ait plus de corps.

Pour ce faire, l’opérateur de virgule est très pratique. Il vous permet de chaîner des expressions 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 d’affectation de valeur) jouent un rôle mineur.

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

Le wikipedia a également un bon article sur la boucle for .

Tout est optionnel dans une boucle for . 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.

La boucle suivante vous amènera dans une boucle infinie. Faites attention en vérifiant la condition.

 for(;;) 

Konrad a mentionné le point clé que je voudrais répéter: la valeur de l’expression la plus à droite est la valeur de l’expression globale.

Un compilateur Gnu a déclaré cet avertissement lorsque j’ai placé deux tests dans la section “condition” de la boucle for

 warning: left-hand operand of comma expression has no effect 

Ce que je voulais vraiment pour la “condition” était deux tests avec un “&&” entre. Selon la déclaration de Konrad, seul le test à droite de la virgule affecterait la condition.

la boucle for est une exécution pour un temps particulier pour (;;)

le syntex pour pour la boucle

pour(;;)

OU

pour (initialiseur; condition; compteur)

par exemple (rmv = 1; rmv < = 15; rmv ++)

exécution à 15 fois pour le bloc

1.initialiser la valeur car démarrer la valeur

(par exemple) rmv = 1 ou rmv = 2

2.seconde déclaration est test la condition est vraie ou fausse, la condition vrai no.de l’exécution du temps la boucle for et la condition est false terminate pour le bloc,

par exemple i = 5; i < = 10 la condition est vraie

 i=10;i<10 the condition is false terminate for block, 

3. tiers est incrémenter ou décrémenter

(par exemple) rmv ++ ou ++ rmv