Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it efficient to declare a variable in a loop? [duplicate]

If I do one of the following (which I assume are equivalent for the purpose of this question)

for(int i=0; i<A; i++)
{
  //... do stuff
  for(int j=0; j<B; j++)
  {
    //... do stuff
  }
  //... do stuff
}

for(int i=0; i<A; i++)
{
  int j;
  //... do stuff
}

Does the variable j get recreated on the stack every loop (is the SP constantly being updated every loop), or is the compiler smart enough to know how many local variables a function might have at one time, and then makes room for all of them on the stack at function entry?

I understand that this is theoretically compiler-dependent, but I assume simple things like this are common across all major compilers. If not, does someone know specifically about GCC and VC++ compilers?

like image 689
Baruch Avatar asked May 26 '13 17:05

Baruch


People also ask

Is it good to declare variables inside for loop?

This is excellent practice. By creating variables inside loops, you ensure their scope is restricted to inside the loop. It cannot be referenced nor called outside of the loop.

Is it bad practice to declare variables in a loop?

It's not a problem to define a variable within a loop. In fact, it's good practice, since identifiers should be confined to the smallest possible scope. What's bad is to assign a variable within a loop if you could just as well assign it once before the loop runs.

Should I declare variable in loop or outside?

If the variable is declared outside the loop, then it has the global scope as it can be used through-out the function and inside of the loop too. If the variable is declared inside the loop, then the scope is only valid inside the loop and if used outside the loop will give an error.

Can we declare a variable inside a loop?

Often the variable that controls a for loop is needed only for the purposes of the loop and is not used elsewhere. When this is the case, it is possible to declare the variable inside the initialization portion of the for.


2 Answers

It is efficient. gcc will optimize that, like most of the modern compilers. Also keep in mind what Donald Knuth said:

We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.

You can check that it is efficient by comparing assembly code. Use for example diff to do the comparison. To generate assembly use -S flag, gcc -S. It is equivalent to gcc -S -O0, because default optimization level is 0. So, even on the lowest level optimizaton, gcc will take care of this variable for you.

First version (for better readability prefer this way):

#include <stdio.h>

int main()
{
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            printf("%d ", i + j);
        }
    }
    return 0;
}

Second version:

#include <stdio.h>

int main()
{
    for (int i = 0; i < 10; i++)
    {
        int j;
        for (j = 0; j < 10; j++)
        {
            printf("%d ", i + j);
        }
    }
    return 0;
}

Identical assembly result:

    .file   "main.cpp"
    .section    .rodata
.LC0:
    .string "%d "
    .text
.globl main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    .cfi_personality 0x3,__gxx_personality_v0
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    movl    $0, -4(%rbp)
    jmp .L2
.L5:
    movl    $0, -8(%rbp)
    jmp .L3
.L4:
    movl    -8(%rbp), %eax
    movl    -4(%rbp), %edx
    leal    (%rdx,%rax), %eax
    movl    %eax, %esi
    movl    $.LC0, %edi
    movl    $0, %eax
    call    printf
    addl    $1, -8(%rbp)
.L3:
    cmpl    $9, -8(%rbp)
    setle   %al
    testb   %al, %al
    jne .L4
    addl    $1, -4(%rbp)
.L2:
    cmpl    $9, -4(%rbp)
    setle   %al
    testb   %al, %al
    jne .L5
    movl    $0, %eax
    leave
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3"
    .section    .note.GNU-stack,"",@progbits

int i is -4(%rbp), int j is -8(%rbp). As you can see int j is not reallocated or something.

like image 160
Adam Stelmaszczyk Avatar answered Oct 24 '22 13:10

Adam Stelmaszczyk


I believe the variables will only be created once, although I do not care and I don't believe you should either.

This is likely an example of pre-optimization (or unnecessary optimization) on your part; the potential inefficiency created by declaring variables within a loop is incredibly small and "optimizing" your code by declaring variables in different locations will have a negligible impact on the overall runtime and memory usage of your program.

Consider spending time optimizing your algorithms and finding efficient data structures, as this will likely be a much better use of your time.

like image 31
Jake Greene Avatar answered Oct 24 '22 14:10

Jake Greene