Question

J'ai vu des boucles très bizarres pour lors de la lecture du code d'autres personnes. J'ai essayé de rechercher une explication de syntaxe complète pour la boucle pour dans C , mais cela est très difficile, car le mot " pour " ; apparaît dans des phrases indépendantes, rendant la recherche presque impossible à Google efficacement.

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

Le pour ici:

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

Dans la condition intermédiaire, une virgule sépare les deux morceaux de code. Que fait cette virgule? Je comprends la virgule à droite car elle fait à la fois a > > = 1 et b < < = 1 .

Mais dans une condition de sortie de boucle, que se passe-t-il? Est-il fermé lorsque p == 0 , lorsque a == 1 ou lorsque les deux se produisent?

Ce serait formidable si quelqu'un pouvait m'aider à comprendre cela et peut-être me diriger vers une description complète de la syntaxe de la boucle pour .

Était-ce utile?

La solution

La virgule n’exclut pas les boucles for; c'est l'opérateur de virgule.

x = (a, b);

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

La syntaxe de pour est:

for (init; condition; increment)
    ...

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

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

Votre exemple de boucle for est donc (encore une fois en ignorant continue et pause ) équivalent à

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

Qui agit comme si c'était (en ignorant à nouveau continue et pause ):

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 ne figuraient pas dans la conversion simplifiée en une boucle while ci-dessus:

  • Si la condition est omise, elle est toujours true (il en résulte une boucle infinie sauf si un break , un goto ou quelque chose d'autre se casse la boucle).
  • Un continue agit comme s'il s'agissait d'une étiquette juste avant l'incrémentation, contrairement à un continue dans la boucle while qui ignorerait l'incrémentation.

De plus, un détail important concernant l'opérateur de virgule: il s'agit d'un point de séquence, comme & amp; & amp; et || (c'est pourquoi je peux le scinder déclarations séparées et garder sa signification intacte).

Modifications 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. Effectivement,

for (...) { ... }

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

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

La norme dit:

  

ISO / CEI 9899: 1999 & 6.8; Instructions d'itération

     

& # 182; 5 Une instruction d'itération est un bloc dont la portée est un sous-ensemble strict de la portée de sa   bloc englobant. Le corps de la boucle est également un bloc dont la portée est un sous-ensemble strict de la portée.   de la déclaration d'itération.

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

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

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

Maintenant, le "bloc enroulé 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 plusieurs variables, 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 & # 167; 6.8.5.3 La déclaration 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é avant chaque exécution du corps de la boucle. L'expression expression-3 est   évalué comme une expression vide après chaque exécution du corps de la boucle. Si la clause 1 est un   déclaration, le champ de toutes les variables qu’il déclare est le reste 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, c'est   évalué comme une expression vide avant la première évaluation de l'expression de contrôle. 133)

     

Les clauses-1 et expression-3 peuvent être omises. Une expression omise-2 est remplacée par un   constante non nulle.

     

133) Ainsi, la clause-1 spécifie l'initialisation de la boucle, 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 telle 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) à effectuer après chaque itération.

Autres conseils

La virgule sépare simplement deux expressions et est valide n'importe où en 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.

Les boucles

pour se composent de trois parties, chacune pouvant également être vide; un (le premier) est exécuté au début et un (le troisième) à la fin de chaque itération. Ces parties initialisent et incrémentent généralement 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 donne false , la boucle est abandonnée. C'est tout ce qu'il y a à faire.

Le style C pour la boucle est composé de trois expressions:

for (initializer; condition; counter) statement_or_statement_block;
  • L'initialiseur s'exécute une fois, lorsque la boucle commence.
  • La condition est vérifiée avant chaque itération. La boucle s'exécute tant 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 valable 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 au préalable 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 y parvenir, l’opérateur par virgule est très utile. 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 de virgule (par exemple, des considérations d'attribution 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 resterais à l’écart jusqu’à ce que je trouve une vraiment bonne raison de le faire. Jouer au golf avec des boucles for rend le code plus difficile à lire et à comprendre (et à maintenir).

La wikipedia propose également un article sur la boucle .

Tout est facultatif dans une boucle pour . Nous pouvons initialiser plus d’une variable, nous pouvons vérifier plusieurs conditions, nous pouvons en itérer plus d’une en utilisant l’opérateur virgule.

La boucle suivante pour vous mènera dans une boucle infinie. Faites attention en vérifiant l'état.

for(;;) 

Konrad a mentionné le point essentiel 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 je mets deux tests dans la "condition". section de la boucle for

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

Ce que je souhaitais vraiment pour la "condition" deux tests avec un " & amp; " " entre. Selon la déclaration de Konrad, seul le test situé à droite de la virgule affecterait la situation.

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

le syntex de la boucle for

pour (;;)

OU

pour (initialiseur; condition; compteur)

p.ex. (rmv = 1; rmv < = 15; rmv ++)

exécution à 15 fois dans le bloc

1.initialisez la valeur car démarrez la valeur

(par exemple) rmv = 1 ou rmv = 2

La deuxième instruction est teste si la condition est vraie ou fausse, la condition vraie no.faire du temps d'exécution de la boucle for et la condition est fausse terminer pour bloc,

Exemple: i = 5; i <10, la condition est vraie

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

3. le troisième est l'incrément ou le décrément

(par exemple) rmv ++ ou ++ rmv

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top