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

Jun 9, 2022 at 6:28pm
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 Jun 9, 2022 at 6:28pm
Jun 9, 2022 at 7:12pm
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 Jun 9, 2022 at 8:01pm
Jun 9, 2022 at 7:39pm
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.
Jun 9, 2022 at 8:01pm
Oh, ooops, fat fingers. Yes, it would be 10.
Jun 10, 2022 at 9:24am
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 Jun 10, 2022 at 9:39am
Jun 10, 2022 at 3:10pm
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.
Jun 16, 2022 at 8:37am
@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 Jun 16, 2022 at 8:38am
Jun 16, 2022 at 9:14am
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 Jun 16, 2022 at 9:16am
Jun 16, 2022 at 9:39am
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 Jun 16, 2022 at 9:39am
Jun 16, 2022 at 9:48am
when it's not in scope...
Jun 16, 2022 at 9:51am
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.
Jun 16, 2022 at 10:02am
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
Jun 16, 2022 at 10:14am
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';
}
Jun 16, 2022 at 10:21am
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.
Jun 16, 2022 at 10:45am
::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...

Jun 16, 2022 at 11:41am
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 Jun 16, 2022 at 11:48am
Jun 16, 2022 at 11:57am
Well yes, if using an additional variable (pointer or ref) then all bets are off. These are c 'tricks'...

Jun 16, 2022 at 12:03pm
These are c 'tricks'...


C doesn't have references.
Jun 16, 2022 at 12:07pm
Yeah - but in C++ a ref is just a pointer 'under the hood'...
Topic archived. No new replies allowed.