"for (int i" vs "for (i"

Is there any reason why choose one over the other?

1
2
3
4
int i;
for (i=0; i<10; i++) {
   // instructions
}


or

1
2
3
for (int i=0; i<10; i++) {
   // instructions
}

I know they do the same thing. Is the latter a better option because it keeps the i declaration within the loop? A subjective view is welcome.

I tried googling it but it's hard to get results when the query contains characters that aren't words.
Last edited on
I know they do the same thing.

They don't do the same thing. Similar, but not "the same."

i in the first snippet persists outside the for loop block. After the block i will have a value of 11 10.

i in the 2nd snippet exists only within the body of the for loop, try to access it after the for loop and you should get a compile error.

Unless there is a need to use the indexing variable outside the code block the 2nd example is preferable.

You should always try to create variables as narrowly scoped as possible, close to first use. C++ is not C.
Last edited on
i in the first snippet persists outside the for loop block. After the block i will have a value of 11.

Why 11? When i reaches 10 the for loop ends.
Oh, ooops, fat fingers. Yes, it would be 10.
Also, in the C language (before C99), you could not declare variables after a statement, nor inside of a for loop. So this would have been the only way to go:
1
2
3
4
5
6
7
8
9
10
void my_function(void)
{
    int i; /* <-- variable declarations must come first! */

    /* possibly more statements here */

    for (i = 0; i < 10; i++) {
        /* ... */
    }
}

...and therefore you'll still find many examples that do it that way.

Declaring the loop counter variable right inside the for statement is a "convenience" feature that results in cleaner/shorter code, as you don't need a separate variable declaration in front of the loop.

Also, it limits the scope of the loop counter variable to the loop, which makes sense most of the time.

(BTW: If you need to know the "final" value of the loop counter after the loop has finished, e.g. because your loop may break early, then you still need to declare the counter variable outside of the loop)
Last edited on
I think they are not the same.
In first snippet, after for loop, you can still use 'i' , because 'i' 's lifetime is not over yet.But in latter snippet, 'i' 's scope is in for loop. So when the for loop is finished, you can not use 'i' any more.
@ningfan666: A simple way to make them the same (roughly) is to force scope it:
1
2
3
4
5
6
7
8
9
int mul( int a, int b )
{
	int c = 0;
	{
		int i;
		for ( i = 0; i < b; ++i, c += a );
	}
	return c;
}

Wasn't until maybe a year ago I learned I could actually do that (because it was only then that it occurred to me to try), alternatively if the compiler you're using freaks out at that then this is also an option:
1
2
3
4
5
6
7
8
9
10
int mul( int a, int b )
{
	int c = 0;
	if ( 1 )
	{
		int i;
		for ( i = 0; i < b; ++i, c += a );
	}
	return c;
}

Or this:
1
2
3
4
5
6
7
8
9
10
11
int mul( int a, int b )
{
	int c = 0;
	do
	{
		int i;
		for ( i = 0; i < b; ++i, c += a );
	}
	while ( 0 );
	return c;
}
Last edited on
awsdert wrote:
if the compiler you're using freaks out at that then ...

There is no reason why the compiler would freak out. It's how C++ works.

If statements and loops are technically defined to only have one statement.

if ( condition ) statement
while ( condition ) statement

{ } creates a compound statement, i.e. a statement that can contain a list of statements. That's how you're able to put multiple statements in if statements and loops. But there is nothing preventing you from using compound statements in other places where you can write statements.
Last edited on
When is i not i ?

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;

int main()
{
   int i = 100;
   for ( int i = 0; i < 10; i++ )
   {
      cout << i << ' ';
   }
   cout << i << '\n';
}
Last edited on
when it's not in scope...
But there is nothing preventing you from using compound statements in other places where you can write statements.


It's common (?) when you have class/struct with constructor(s)/destructor and you want the destructor called. Put the class variable and it's usage within a compound statement when when the compound statements 'end' then the destructor is called.
This could be useful when using std::scoped_lock.

1
2
3
4
5
6
{
    std::scoped_lock lock(mutex); // lock 

    // do things while the mutex is locked...

} // unlock 

https://en.cppreference.com/w/cpp/thread/scoped_lock
Ah, I wonder how many different i variables you can get access to.

There has to be a way of getting that i=100 from within the inner loop ... just haven't found it yet!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;

int i = 42;

int main()
{
   int i = 100;
   for ( int i = 0; i < 10; i++ )
   {
      cout << i << ' ' << ::i << ' ';
   }
   cout << i << '\n';
}
There has to be a way of getting that i=100 from within the inner loop ... just haven't found it yet!

I'm pretty sure there isn't. Just use different names. It's less confusing.
::i uses the global scope so the value is always 42 (uses i defined on L4). I don't know of a way to access i as defined on L8. It's not in scope and isn't in the global scope...

Well, you can certainly change the value of the outer i within the loop (albeit indirectly), so you can definitely access it. You just can't refer to it by name.

And before anybody complains I am absolutely NOT advocating doing this - just investigating what is possible.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;

int main()
{
   int i = 100;
   int *p = &i;
   for ( int i = 0; i < 10; i++ )
   {
      cout << i << ' ';
      *p = 99;
   }
   cout << i << '\n';
}


0 1 2 3 4 5 6 7 8 9 99




Similar, with reference, not pointer.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;

int main()
{
   int i = 100;
   int &p = i;
   for ( int i = 0; i < 10; i++ )
   {
      cout << i << ' ';
      p = 99;
   }
   cout << i << '\n';
}
Last edited on
Well yes, if using an additional variable (pointer or ref) then all bets are off. These are c 'tricks'...

These are c 'tricks'...


C doesn't have references.
Yeah - but in C++ a ref is just a pointer 'under the hood'...
Topic archived. No new replies allowed.