Can a 'for' loop inside of a 'for' loop use the same counter variable name?

22,806

Solution 1

You may use the same name (identifier). It will be a different object. They will not affect each other. Inside the inner loop, there is no way to refer to the object used in the outer loop (unless you make special provisions for that, as by providing a pointer to it).

This is generally bad style, is prone to confusion, and should be avoided.

The objects are different only if the inner one is defined separately, as with the int i you have shown. If the same name is used without defining a new object, the loops will use the same object and will interfere with each other.

Solution 2

First, this is absolutely legal: the code will compile and run, repeating the body of the nested loop 10×10=100 times. Loop counter i inside the nested loop will hide the counter of the outer loop, so the two counters would be incremented independently of each other.

Since the outer i is hidden, the code inside the nested loop's body would have access only to the value of i of the nested loop, not i from the outer loop. In situations when the nested loop does not need access to the outer i such code could be perfectly justifiable. However, this is likely to create more confusion in its readers, so it's a good idea to avoid writing such code to avoid "maintenance liabilities."

Note: Even though the counter variables of both loops have the same identifier i, they remain two independent variables, i.e. you are not using the same variable in both loops. Using the same variable in both loops is also possible, but the code would be hard to read. Here is an example:

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

Now both loops use the same variable. However, it takes a while to figure out what this code does without compiling it (demo);

Solution 3

You can. But you should be aware of the scope of the is. if we call the outer i with i_1 and the inner i with i_2, the scope of the is is as follows:

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
}

You should notice that they do not affect each other, and just their scope of definition is different.

Solution 4

That is completely possible but keep in mind, you wont be able to address the first declared i

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

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

    }
}

in the second loop within the second child loop

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
    }
}

if you need to adjust or get the value of the first i, use j in the second loop

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

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

    }
}

and if your creative enough you can do both of them in one loop

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

Solution 5

Yes you can use the same counter variable name for an inner for loop as for the outer for loop.

From for loop:

for ( init_clause ; cond_expression ; iteration_expression ) loop_statement
The expression statement used as loop_statement establishes its own block scope, distinct from the scope of init_clause.

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

The scope of loop_statement is nested within the scope of init_clause.

From C Standards#6.8.5p5 Iteration statements [emphasis mine]

An iteration statement is a block whose scope is a strict subset of the scope of its enclosing block. The loop body is also a block whose scope is a strict subset of the scope of the iteration statement.

From C Standards#6.2.1p4 Scopes of identifiers [emphasis mine]

....Within the inner scope, the identifier designates the entity declared in the inner scope; the entity declared in the outer scope is hidden (and not visible) within the inner scope.

Share:
22,806

Related videos on Youtube

Uclydde
Author by

Uclydde

Studying computer science at the University of Central Florida.

Updated on November 22, 2021

Comments

  • Uclydde
    Uclydde over 2 years

    Can I use the same counter variable for a for loop inside of a for loop?

    Or will the variables affect each other? Should the following code use a different variable for the second loop, such as j, or is i fine?

    for(int i = 0; i < 10; i++)
    {
      for(int i = 0; i < 10; i++)
      {
      }
    }
    
    • Jonathan Leffler
      Jonathan Leffler almost 6 years
      It is confusing — it wouldn't get past me in a code review. But it is legitimate. There are two different variables both called i, with different scopes. Use -Wshadow with GCC to get such problems reported automatically.
    • leftaroundabout
      leftaroundabout almost 6 years
      I'm surprised that -Wshadow is not included in -Wall.
    • Jörg W Mittag
      Jörg W Mittag almost 6 years
      Your question is unclear. In your title and in your question, you ask about using "the same counter variable", but in your code example you use different counter variables. What, precisely is it you are asking about?
    • Cubic
      Cubic almost 6 years
      @leftaroundabout -Wshadow warns about shadowing of global variables as well, which could easily get annoying in larger projects.
    • hyde
      hyde almost 6 years
      @leftaroundabout even more surprisingly, even -Wextra does not include -Wshadow. I guess it is common enough in some projects, or some gcc developer loves shadowing as a coding style, to warrant being left out like this.
    • Konrad Rudolph
      Konrad Rudolph almost 6 years
      @leftaroundabout Echoing what Cubic said, -Wshadow has a horrendous false positive rate, rendering it completely useless. Scope exists for a reason, and shadowing is a priori not problematic. Now -Wshadow-local (note: not -Wshadow=local) is very different. But unfortunately GCC has so far refused to include it in trunk (though there appear to be forks of GCC which do include it).
    • David Z
      David Z almost 6 years
      @JörgWMittag I think JBraha was taking it for granted that there is a one-to-one mapping between names and variables, i.e. that both times i was used in the code sample, it refers to the same variable. That seems like a reasonable thing for less-experienced C programmers to assume, even though it turns out not to be correct. I made an edit that should clarify the question, hopefully without changing the meaning - but if I have changed the meaning, someone please fix it.
    • Quentin 2
      Quentin 2 almost 6 years
      It actually says "use the same name". There are two variables with the same name.
    • David Hammen
      David Hammen almost 6 years
      @KonradRudolph - Just to reiterate, there are some organizations that think that shadowing is a good thing in the right contexts. For example, a C++ constructor or setter that takes arguments with the exact same names as the data members to be constructed or set. I've been told by some that I should use the same names in this context, served with a dish of "did you even read our coding standards" served on the side, while others have said that I absolutely shouldn't do that, served with a dish of "did you even read our coding standards" on the side.
  • Easton Bornemeier
    Easton Bornemeier almost 6 years
    Since the question is phrased as "using the same counter variable" I would also like to point out that the shadowing only takes place when the redefinition occurs. Omitting the int on the inner for loop, i.e. actually using the same counter variable, will cause the outer loop to only run once, as the inner loop will leave i == 10. This is trivial, but thought it provides clarification given how the question was stated
  • Sergey Kalinichenko
    Sergey Kalinichenko almost 6 years
    @EastonBornemeier You are right, I figured I should address the issue of "the same variable" in the body of the answer. Thank you!
  • Sergey Kalinichenko
    Sergey Kalinichenko almost 6 years
    @EricPostpischil "Variable shadowing" is an official term, complete with its own page on wikipedia. I've updated the answer to be consistent with the wording of the standard, though. Thank you!
  • Eric Postpischil
    Eric Postpischil almost 6 years
    @dasblinkenlight: Actually, I had a brain spasm about the direction, and the inner name does shadow the outer name. My previous comment was wrong in that regard. My apologies. (However, that is in an English sense, not in an official sense—Wikipedia is not an official publication for C or programming in general, and I am not aware of any office or authoritative body that defines the term.) The C standard uses “hide,” so that is preferable.
  • TripeHound
    TripeHound almost 6 years
    Nice, especially with the "same variable" example. However, I think "the code will compile and run as expected" would be better as "the code will compile and run as someone who has read it carefully and understands all the ramifications expected" ... as you say, code like this "is likely to create more confusion in its readers" and the problem is a confused reader might expect something other than what it does.
  • KYL3R
    KYL3R almost 6 years
    using for(i) and for(j) nested, and inside i++, will increase the outer-loop variable. However what you say is correct if you use the same identifier in both loops, because they are differently scoped variables.
  • Bloodgain
    Bloodgain almost 6 years
    If I caught shadowed i variables in nested loops during a code review, I'd see it as a coaching opportunity. If I caught someone obfuscating the inner loop like your last example (that is NOT one loop), I might throw them out a window.
  • Eric Postpischil
    Eric Postpischil almost 6 years
    @BloodGain: “Object” is a technical term used in the C standard. I used it deliberately here.
  • Bloodgain
    Bloodgain almost 6 years
    @EricPostpischil: Ah, I see, yes. I was not aware of that definition in the standard, and was afraid it would be misleading to new programmers (as this is very clearly a beginner question), since C does not have "objects" in the sense that we generally use the term. I see it in the C11 standard, and now I'm curious if it was defined that way before C11.
  • Bloodgain
    Bloodgain almost 6 years
    It was. It's 3.14 in the C99 standard, instead of 3.15. So no excuse on my part. That'll teach me to question you <:-|
  • Dodo
    Dodo almost 6 years
    it is one loop, it has only one for loop, if it was 2 it would have two for keywords or two while keywords or a for and while keywords
  • Bloodgain
    Bloodgain almost 6 years
    That's why I said you obfuscated the loop. You're still looping, you've just hidden it with less obvious syntax. And it's worse in every way for it.
  • Isaac Rabinovitch
    Isaac Rabinovitch over 5 years
    More generally: there's nothing to prevent you from re-using a variable name in any nested scope. Except, of course, the fear of God's Punishment for writing confusing code.
  • Jeremy Caney
    Jeremy Caney over 2 years
    There are twelve existing answers to this question, including an accepted answer with 142 upvotes. Are you sure your answer hasn't already been provided? If not, why might someone prefer your approach over the existing approaches proposed? Are you taking advantage of new capabilities? Are there scenarios where your approach is better suited?
  • kevinarpe
    kevinarpe about 2 years
    Is there a compiler (GCC, etc) argument to explicitly forbid this type of code? I recently wrote code exaclty like this... It was like a joke of electricity finding this "bug" -- How was this allowed by my compiler (GCC)???
  • Eric Postpischil
    Eric Postpischil about 2 years
    @kevinarpe: It is allowed by your compiler because it is a desired and intentional specified part of the C language. It is generally not a problem because people rarely stick one loop inside another that needs an identifier of the outside loop without paying attention to the newly inserted loop. On the other hand, a “self contained” loop may be inserted inside another loop, sometimes by way of a macro, and it does not need or care about identifiers of the outer loop. As a matter of actual practice, this is sometimes a convenience and is rarely a problem, so warning about it is off by default.
  • Eric Postpischil
    Eric Postpischil about 2 years
    @kevinarpe: Nonetheless, GCC and Clang have a switch to warn about it, -Wshadow, or the more specific -Wshadow=local that warns only if a local identifier shadows another local identifier.