Je suis tombé sur une boucle for dans le code qui ressemble à ceci:
for ( argc--, argv++; argc > 0; argc--, argv++ )
Comment ça marche? Normalement, une boucle for
ressemble à ceci:
for (initialization; condition; increment) {/*body of the loop*/}
Mais cela ne contient aucune virgule - que signifient les virgules et qu’elles font?
Dans la norme C (6.8.5.3 La déclaration for), la déclaration for est présentée sous la forme suivante
for ( clause-1 ; expression-2 ; expression-3 ) statement
et selon le clause-1 il est écrit
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.
Dans cette déclaration
for ( argc--, argv++; argc > 0; argc--, argv++ )
clause-1 est l'expression argc--, argv++
basée sur l'opérateur de virgule. D'après le standard C (opérateur de virgule 6.5.17).
2 L'opérande gauche d'un opérateur de virgule est évalué comme une expression vide ; il y a un point de séquence entre son évaluation et celui de l'opérande droit. Ensuite, l'opérande de droite est évalué. le résultat a son type et sa valeur.
La seule particularité est que le résultat de l'opérateur n'est pas utilisé dans l'instruction for. L'expression est utilisée pour ses effets secondaires.
Habituellement, le premier paramètre transmis à un programme en cours d'exécution est son nom. L'expression dans la clause-1 ignore ce premier paramètre.
Comparez la sortie de ces deux programmes. Supposons que l'utilisateur spécifie des paramètres de ligne de commande
first second third
Le programme de sortie de ce programme
#include <stdio.h>
int main( int argc, char * argv[] )
{
for ( argc--, argv++; argc > 0; argc--, argv++ )
{
puts( *argv );
}
return 0;
}
est
first
second
third
et la sortie du programme de ce programme lorsque le clause-1 est vide (ni expression ni déclaration)
#include <stdio.h>
int main( int argc, char * argv[] )
{
for ( /*argc--, argv++*/; argc > 0; argc--, argv++ )
{
puts( *argv );
}
return 0;
}
est
./prog.exe
first
second
third
Pour que l'opérateur de virgule soit clair, considérez un programme comme le premier programme de démonstration où, au lieu de la boucle for, une boucle while est utilisée.
#include <stdio.h>
int main( int argc, char * argv[] )
{
while ( argv++, --argc > 0 )
{
puts( *argv );
}
return 0;
}
Le résultat sera le même que dans le premier programme de démonstration
first
second
third
Voici dans l'instruction while, on utilise également l'opérateur virgule. La différence est que dans ce cas, la valeur de l'opérateur de virgule est utilisée comme valeur de la condition.
Faites attention à ce que le expression-3 représente également à lui seul une expression avec l'opérateur virgule.
De plus, comme la question est marquée avec la balise C++, vous devez savoir que, en C++, la deuxième clause de l'instruction for (en C++, elle s'appelle condition) peut également être une expression ou une déclaration.
Comme déjà indiqué dans plusieurs réponses, il s’agit de l’opérateur virgule , donc
argc--, argv++
est seulement un expression.
L'opérateur par virgule évalue les deux côtés, d'abord à gauche, puis à droite. Le résultat est celui du côté droit. Donc, vous pourriez écrire des choses étranges comme
int a = (x += 5, x + 2);
cela ajouterait 5 à x avant d'attribuer le résultat de x + 2
à a
. Un tel code est source de confusion et doit être évité. Mais cela démontre une propriété importante de l'opérateur virgule :
Il agit comme un point de séquence : Avec le code ci-dessus, vous avez la garantie que 5 a déjà été ajouté à x (la valeur de x en effet changé), avant l'évaluation de x + 2
.
La principale utilisation judicieuse de l'opérateur de virgule est celle indiquée dans votre question. Il est utile dans les boucles for
plus complexes d’avoir par exemple effets secondaires multiples et un séquençage garanti.
Pour clarifier la raison pour laquelle la séquence pourrait être importante (ce n'est pas dans votre exemple car les effets secondaires ne dépendent pas les uns des autres), regardez cet exemple (artificiel):
int i, j;
for (i = j = 0; i < 10; ++i, j+=i)
{
printf("%d\n", j);
}
Si l'opérateur de virgule n'a pas introduit de point de séquence ici, vous ne saurez pas si j+=i
ajouterait la valeur incrémentée i
ou celle non incrémentée.
Pour les initialisations multiples et les mises à jour/incrémentales multiples, nous utilisons comma operator(,)
. . Nous séparons chaque instance par un comma(,)
.
Dans ce cas, lors de la saisie de la boucle for, les deux expressions argc--
et argv++
de la partie initialisation sont exécutées. À partir de ce moment, à chaque fois que la boucle est itérée, les expressions argc--
et argv++
sont en la partie incrémentielle est exécutée.
Dans cette for
boucle opérateur virgule est utilisé dans les première et dernière expressions. Donc, la déclaration for
est comme
for(
(argc--, argv++); // Expression 1
argc > 0; // Expression 2
(argc--, argv++) // Expression 3
)
Il n'y a que trois expressions (argc--, argv++)
, argc > 0
et (argc--, argv++)
.
L’expression 1 ne doit pas nécessairement être une déclaration, elle peut être toute expression valide ou même être omise.
for(;expression2; expression3)
ou toutes les expressions peuvent être omises
for(;;)
Dans la boucle for, (argc--, argv++)
est utilisé comme première expression pour mettre à jour les variables argc
et argv
(argc
sera décrémenté de 1 et le pointeur argv
sera incrémenté de 1). Une fois que l'effet secondaire sur ces variables est effectué, le programme entre dans le corps de la boucle après avoir vérifié argc > 0
pour true
. C'est ce qui arrive quand tu fais
for( i = 1; i < 10; i++)
i = 1
update i
to 1
et la condition est vérifiée. Cette mise à jour de i
n'est effectuée qu'une fois, puis pour le reste, elle est mise à jour par l'expression i++
.
for ( argc--, argv++; argc > 0; argc--, argv++ ) { ... }
Fait ce qui suit:
argc
et increment argv
argv > 0
, si ce n'est pas le cas, quittez la boucle.{ ... }
argc
et increment argv
Comme " Initialisation " et " Updation " sont identiques, cela pourrait aussi être écrit
while (argc--, argv++, argc > 0)
{ ... }
Cette expression
(argc--, argv++, argc > 0)
se compose de trois sous-expressions séparées par l'opérateur virgule .
Ces sous-expressions sont exécutées de gauche à droite.
L'expression entière évalue le résultat de la sous-expression la plus à droite.
for ( argc--, argv++; argc > 0; argc--, argv++ )
signifie que la boucle commence avec les valeurs de argc
, argv
définies sur moins 1 et plus 1 de leurs valeurs initiales correspondantes. Chaque itération diminuera et augmentera leurs valeurs et s'arrêtera une fois que argc
atteindra 0 (ce qui signifie que tous les arguments d'entrée ont été lus).
Le paramètre d'initialisation dans la boucle for ne signifie pas uniquement l'initialisation d'une variable ayant une valeur particulière.
Il peut également avoir une ou plusieurs expressions régulières séparées par une virgule.
J'espère que ça va aider !!
for ( argc--, argv++; argc > 0; argc--, argv++ )
peut être lu comme
for ( (argc--), argv++; argc > 0; (argc--), argv++ )
l'opérateur de virgule ayant la priorité la plus basse possible, l'opérateur de gauche sera toujours évalué en premier
argv possède des arguments en ligne de commande. Cependant, le tout premier est le nom du programme.
Ainsi, la boucle commence à argv[1]
et traite tous les arguments donnés par la ligne de commande sans traiter le nom du programme