web-dev-qa-db-fra.com

Une boucle 'for' à l'intérieur d'une boucle 'for' peut-elle utiliser le même nom de variable de compteur?

Puis-je utiliser la même variable de compteur pour une boucle for à l'intérieur d'une boucle for?

Ou les variables vont-elles s’affecter? Le code suivant doit-il utiliser une variable différente pour la deuxième boucle, telle que j, ou bien i fine?

for(int i = 0; i < 10; i++)
{
  for(int i = 0; i < 10; i++)
  {
  }
}
104
Uclydde

Vous pouvez utiliser le même nom (identifiant). Ce sera un objet différent. Ils ne vont pas s’affecter. À l'intérieur de la boucle interne, il n'y a aucun moyen de faire référence à l'objet utilisé dans la boucle externe (à moins que vous n'ayez prévu de le faire, par exemple en lui fournissant un pointeur).

Ceci est généralement mauvais style, est sujet à confusion et devrait être évité.

Les objets ne sont différents que si l'objet interne est défini séparément, comme avec le int i que vous avez montré. Si le même nom est utilisé sans définir de nouvel objet, les boucles utiliseront le même objet et interféreront les unes avec les autres.

136
Eric Postpischil

Tout d'abord, ceci est tout à fait légal: le code sera compilé et exécuté en répétant le corps de la boucle imbriquée 10 × 10 = 100 fois. Le compteur de boucles i à l'intérieur de la boucle imbriquée va masquer le compteur de la boucle externe afin que les deux compteurs soient incrémentés indépendamment l'un de l'autre.

Puisque la variable i extérieure est masquée, le code situé à l'intérieur du corps de la boucle imbriquée aurait uniquement accès à la valeur de i de la boucle imbriquée, et non à i de la boucle externe. Dans les cas où la boucle imbriquée n'a pas besoin d'accéder à l'extérieur i, ce code pourrait être parfaitement justifié. Cependant, cela risque de créer davantage de confusion chez ses lecteurs. Il est donc judicieux d'éviter d'écrire un tel code pour éviter les "obligations de maintenance".

Remarque: Même si les variables de compteur des deux boucles ont le même identificateur i, elles restent deux variables indépendantes, c'est-à-dire que vous êtes pas en utilisant la même variable dans les deux boucles. L'utilisation de la même variable dans les deux boucles est également possible, mais le code serait difficile à lire. Voici un exemple:

for (int i = 1 ; i < 100 ; i++) {
    for ( ; i % 10 != 0 ; i++) {
        printf("%02d ", i);
    }
    printf("%d\n", i);
}

Maintenant, les deux boucles utilisent la même variable. Cependant, il faut un certain temps pour comprendre ce que fait ce code sans le compiler ( demo );

55
dasblinkenlight

Vous pouvez. Mais vous devez être conscient de la portée de la is. si nous appelons la i extérieure avec i_1 et la i intérieure avec i_2, la portée de la is est la suivante:

for(int i = 0; i < 10; i++)
{
     // i means i_1
     for(int i = 0; i < 10; i++)
     {
        // i means i_2
     }
     // i means i_1
}

Vous devriez remarquer qu’ils ne s’affectent pas et que leur champ de définition est différent.

25
OmG

C’est tout à fait possible, mais n’oubliez pas que vous ne pourrez pas vous adresser à le premier déclaré i

for(int i = 0; i < 10; i++)//I MEAN THE ONE HERE
{

  for(int i = 0; i < 10; i++)
    {

    }
}

dans la deuxième boucle dans la deuxième boucle enfant

for(int i = 0; i < 10; i++)
{

  for(int i = 0; i < 10; i++)//the new i
    {
        // i cant see the i thats before this new i here
    }
}

si vous devez ajuster ou obtenir la valeur du premier i, utilisez j dans la deuxième boucle

for(int i = 0; i < 10; i++)
{

  for(int j = 0; j < 10; j++)
    {

    }
}

et si votre créativité est suffisante, vous pouvez faire les deux en une boucle

for(int i ,j= 0; i < 10; (j>9) ? (i++,j=0) : 0 ,j++)
{
    printf("%d %d\n",i,j);
}
16
Dodo

Oui, vous pouvez utiliser le même nom de variable de compteur pour une boucle interne for que pour la boucle externe for.

De pour la boucle :

for ( init_clause ; cond_expression ; iteration_expression ) loop_statement
L'instruction d'expression utilisée en tant que loop_statement établit sa propre portée de bloc , distincte de la portée de init_clause .

for (int i = 0; ; ) {
    long i = 1;   // valid C, invalid C++
    // ...
}  

La portée de loop_statement est imbriquée dans la portée de init_clause .

Extrait des normes C n ° 6.8.5p5 Instructions d'itération [italiques]

Une instruction d'itération est un bloc dont la portée est un sous-ensemble strict de la portée de son 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 l'instruction d'itération .

Tiré de la norme C 6.2.1p4 Portée des identificateurs [l'emphase mienne]

.... Dans la portée interne, l'identifiant désigne l'entité déclarée dans la portée interne; l'entité déclarée dans la portée externe est masquée (et non visible) dans la portée interne.

12
H.S.

Du point de vue du code/compilateur, ce serait une chose parfaitement valide et légale à faire. Le int i déclaré dans la boucle intérieure for(int i = 0; i < 10; i++) se trouve dans une nouvelle portée plus petite, de sorte que la déclaration ombres la déclaration de int i dans la boucle extérieure (ou, avec d'autres mots: Dans la portée interne, tous les accès à la variable i vont au int i déclaré dans la portée intérieure, laissant le int i intact dans la portée extérieure).

Cela dit, du point de vue de la qualité du code, cela est absolument horrible. Il est difficile à lire, difficile à comprendre et facile à mal comprendre. Ne le fais pas.

9
CharonX

Oui, vous pouvez l'utiliser mais c'est assez déroutant. La chose la plus importante est la portée de la variable locale dans la boucle. Dans la mesure où une variable est déclarée à l'intérieur d'une fonction, la portée de cette variable est cette fonction.

int a = 5;
// scope of a that has value 5
int func(){
    int a = 10;
   // scope of a that has value 10
}
// scope of a that has value 5

De même que pour les boucles, les variables déclarées à l'intérieur de la boucle interne ont une portée différente et les variables déclarées, la boucle externe a une portée différente.

for(int i = 0; i < 10; i++){
    // In first iteration, value of i is 0

    for(int i = 1; i < 10; i++){
        // In first iteration, value of i is 1
    }
    // In first iteration, value of i is 0
}

La meilleure approche consiste à utiliser différentes variables pour les boucles internes et externes.

for(int i = 0; i < 10; i++){

    for(int j = 1; j < 10; j++){

    }

}
8
Safwan Shaikh

Oui, vous pouvez utiliser la même variable de nom.

Les variables de programmation C peuvent être déclarées à trois endroits:
variables locales: -Dans une fonction ou un bloc.
Variables globales: -Out de toutes les fonctions.
Paramètres formels: -Dans les paramètres de la fonction.

Mais dans votre cas, i scope devra faire attention aux choses ci-dessous

for(int i = 0; i < 10; i++)
{
     // i means 1st for loop variable
     for(int i = 0; i < 10; i++)
     {
        // but here i means 2nd for loop  variable
     }
     //interesting thing here i means 1st for loop variable
}

Remarque: il serait préférable d’utiliser différentes variables pour les boucles internes et externes.

8
Zaynul Abadin Tuhin

Oui, et encore plus intéressant, vous pouvez réutiliser un nom de variable chaque fois que vous ouvrez un jeu d’accolades. Ceci est souvent utile lors de l’insertion d’un code de diagnostic. Tapez une accolade ouverte '{' suivie de la déclaration et de l'utilisation de variables, puis fermez l'accolade et les variables disparaissent. Cela garantit que vous n'interférerez avec rien dans le corps principal tout en conservant l'avantage des variables, classes et méthodes déclarées en dehors des accolades.

6
SuwaneeCreek

Scope Rule: Une variable déclarée dans une instruction for ne peut être utilisée que dans cette instruction et dans le corps de la boucle.

Si, dans votre code, vous avez défini plusieurs instances de i dans des boucles internes, chaque instance occupera son propre espace mémoire. Il n'y a donc rien à craindre des résultats, de toute façon, ce serait la même chose.

int main(void) {

    int i = 2; //defined with file global scope outside of a function and will remain 2
    if(1)
    {       //new scope, variables created here with same name are different
        int i = 5;//will remain == 5
        for(int i = 0; i < 10; i++)
        {   //new scope for "i"

            printf("i value in first loop: %d \n", i); // Will print 0 in first iteration
            for(int i = 8; i < 15; i++) 
            {   //new scope again for "i", variable with same name is not the same
                printf("i value in nested loop: %d \n", i); // Will print 8 in first iteration
            }
        }

    }

    return 0;
}

Cependant, il n'est pas recommandé d'utiliser le même nom de variable car il est difficile à comprendre et devient par la suite un code non maintenable.

3
Subash J

L'important est que le paramètre de boucle interne contienne int i. Comme i est redéfini de cette façon, les deux variables ne s’affectent pas; leurs champs d'application sont différents. Voici deux exemples pour montrer ceci:

for(int i = 0; i < 10; i++) // This code will print "Test" 100 times
{
 for(int i = 0; i < 10; i++)
 {
  puts("Test");
 }
}

Notez que le code ci-dessus inclut int i dans le paramètre de boucle interne et que le code ci-dessous ne comprend que i.

for(int i = 0; i < 10; i++) // This code will print "Test" 10 times
{
 for(i = 0; i < 10; i++)
 {
  puts("Test");
 }
}
1
Uclydde

Eh bien, vous pouvez le faire sans que vos scripts aient un problème, mais vous devriez éviter cette structure. Cela mène généralement à la confusion

0
Bonfire