For loops; Initialization vs Reusing

Here is something I have been wondering about for a while. I think I know the answer, but I want to hear from some experts. It's mainly a question of efficiency and performance hit.

Let's say you have several 'For' loops back to back; Is it better declare the counter variable a single time in a function, and then reuse it over again for future 'For' loops within the same function, or declare and initialize for each 'For' loop.

Here is an example of what I mean, respectively.

Example 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void main()
{
    sampleFunction();

}

void sampleFunction()
{
    short counter;

    for(counter = 0; counter < 10; counter++)
    {
        //---Insert code here

    }

//--------Code

//--------Code

//--------Code

    for(counter = 0; counter < 10; counter++)
    {
        //---Insert code here

    }

//--------Code

//--------Code

//--------Code

//--------Code

    for(counter = 0; counter < 10; counter++)
    {
        //---Insert code here

        //---Insert code here
    }
}



Versus........

Example 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void main()
{
    sampleFunction();

}

void sampleFunction()
{
    
    for(short counter = 0; counter < 10; counter++)
    {
        //---Insert code here

    }

//--------Code

//--------Code

//--------Code

    for(short counter = 0; counter < 10; counter++)
    {
        //---Insert code here

    }

//--------Code

//--------Code

//--------Code

//--------Code

    for(short counter = 0; counter < 10; counter++)
    {
        //---Insert code here

        //---Insert code here
    }
}



My instincts tell me this:
Example 1 might run slightly faster since it only makes a single declaration and reuses that variable for the rest of the function. However, since it keeps that variable in memory for the entire function, it means more memory is consumed for the duration of the function, which also means less memory is available for execution of other code outside of the 'For' loops.

Example 2 might run a bit slower since it constantly has to find and set aside a spot in memory for each new declaration in a 'For' loop. However, since it releases the memory every time a 'For' loop ends, it means more memory is available for code execution outside of the 'For' loops.
closed account (S6k9GNh0)
Example 1 is a C89 method of doing things. Compilers are able to optimize this. I'm unsure of how scope variables like this are even handled (internally or in general case) so I'm unsure if it would make any difference at all.
Last edited on
In practice both will run just as fast, especially if you turn on compiler optimizations.

The second example has the benefit of clarity: the programmer knows immediately what the type of counter is, because it's written right next to it.

Example 2 might run a bit slower since it constantly has to find and set aside a spot in memory for each new declaration in a 'For' loop. However, since it releases the memory every time a 'For' loop ends, it means more memory is available for code execution outside of the 'For' loops.

I may be wrong, but I'm pretty sure that your count variables are basically local variables that are scoped to each of the for() loops.

This means that when the function is entered, space for all of them is already allocated, and will be deallocated for all of them when the function returns. So in the end, I guess a tiny bit more stack space will be used, but this is insignificant for performance.

Edit: of course, I may be wrong... and perhaps something like alloca() is used internally.
http://linux.die.net/man/3/alloca
Last edited on
> In practice both will run just as fast,

Yes.


> count variables are basically local variables that are scoped to each of the for() loops.
> This means that when the function is entered, space for all of them is already allocated

In practice, it is easy for the compiler to optimize away a local variable altogether. And the smaller the scope in which a local variable is visible, the easier it is to optimize it away. Restricting programmatic visibility leads to clearer code; it also leads to potentially more optimal code.

The compiler knows quite a lot about what is really going on; for instance, by nothing more than static flow analysis and constant-folding:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*  g++ -std=c++11 -Wall -Wextra -pedantic-errors -O3 -fomit-frame-pointer -c -S test.cc */
/* .ident	"GCC: (GNU) 4.9.0 20131020 (experimental)" */

int foo()
{
    int result = 0 ;

    int counter ;
    for( counter = 0; counter < 10; counter++ ) result += counter*2 ;
    for( counter = 0; counter < 10; counter++ ) result -= counter ;

    return result ;

    // generated code: return 45 ;
    /*
    __Z3foov:
        movl	$45, %eax
        ret
    */
}

int bar()
{
    int result = 0 ;

    for( int counter = 0; counter < 10; counter++ ) result += counter*2 ;
    for( int counter = 0; counter < 10; counter++ ) result -= counter ;

    return result ;

    // generated code: return 45 ;
    /*
    __Z3foov:
        movl	$45, %eax
        ret
    */
}

Thank you all for the feedback.

In the case of extremely limited resources, both will still run just as fast as the other?
> both will still run just as fast as the other?

In almost all normal situations, yes.

If anything, Example 2 might run faster than Example 1.


BTW: unless you are using a freestanding implementation ( 'In the case of extremely limited resources' suggests that you might be), main() must return int.
Topic archived. No new replies allowed.