0

Code snippet:

void function(void)
{
    while(1)
    {
         int i = 0;
         i += 1;
         if(i == 500) break;
    }
}

The variable i is stored in stack every time when restart the loop ? What is the memory structure when running this code ? What is the behavior of this variable ? It is a bad or good practice do this ?

Thanks.

ViniciusArruda
  • 970
  • 12
  • 27

4 Answers4

4

You will never reach i == 500. It's being reset every time through the loop since it's within the scope of while(1){}.

The following will work.

void function(void)
{
    int i = 0;
    while(1)
    {
         i += 1;
         if(i == 500) break;
    }
}
rost0031
  • 1,894
  • 12
  • 21
1

When a function runs in C, it allocates space for all the local variables its going to need. If the variables are allocated all next to each other at the top of the function its easy to see how it works:

void foo(){
    int x;
    int y;

    y = 1;
    x = y + 2;
    return x + y;
}

If the variables are declared inside inner blocks of the function, what the compiler does is "lift" those variable declarations to the top of the function. If there are variables with clashing names, the compiler renames things for you so they reference the correct variable.

// This is what you write
void original(){
    int x = 0;
    while(1){
        int x = 1;
    }
}

// This is what the compiler "sees"
void lifted(){
    int x1;
    int x2;
    x1 = 0;
    while(1){
        x2 = 0;
    }
}

In your case, your code is behaving like this one:

void function(void)
{
    int i;
    while(1)
    {
         i = 0;
         i += 1;
         if(i == 500) break;
    }
}

In this version, its clear that the i is being reset to 0 all the time, which is why the loop will run forever.


As for if declaring variables in inner scopes is a good practice or not, it doesn't have to do with memory usage but with the scope of your variable names. In general its a good thing to keep your variables confined to inner scopes if possible (for the same reason why local variables are preferred to global ones). That said, you always have to initialize your variables before the loop and not inside it. In this case, its about removing bugs and not about being a best practice.

hugomg
  • 68,213
  • 24
  • 160
  • 246
  • So whenever a function is called, for all the variables that exist in the function, a space of memory on stack will be reserved, and they will be available when called in its scope. Is that right ? What I want to know is the difference between always declare variables in start of function and in other scope such a `while` or any `{}`. – ViniciusArruda May 19 '15 at 02:49
  • 1
    Yes, all the space is reserved upfront and where you declare variables is just a matter of [controlling the scopes where they are visible](http://stackoverflow.com/a/8474123/90511). – hugomg May 19 '15 at 13:01
  • 1
    One thing you should keep in mind is that an optimizing compiler won't naively allocate space for each variable. Its going to reason about the variables as if they were "virtual registers" and then use a register allocation and spilling procedures to determine what needs to be stored in memory. This can result in some variables always staying in registers and never spilling in memory, more than one variable being stored in the same memory (because the lifetimes do not overlap) or even temporary results from expression evaluation being spilled to memory due to a lack of registers. – hugomg May 19 '15 at 13:04
  • The tldr of this is that when you use an optimizing compiler where you declare your variables really is just about name scoping. The compiler is very clever about how to best allocate memory and registers for things. – hugomg May 19 '15 at 13:06
1

Logically speaking, each iteration of the loop creates a new instance of the i variable which only exists within the body of the loop. As written, this code will never terminate, because each iteration of the while loop creates a new instance of i and initializes it to 0.

Attempting to reference i outside the body of the loop results in undefined behavior; IOW, code like

int *p;
while ( 1 )
{
  int i = 0;
  p = &i;
  if ( some_condition )
    break;
  ...
}

printf( "last value of i was %d\n", *p );

isn't guaranteed to do what you expect.

In practice, the generated machine code will set aside the space for i once at function entry; however, you should not rely on that behavior.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • @Bode `i` will be created when the scope start ? (I mean, a memory space will be reserved for `i` when the scope start). – ViniciusArruda May 19 '15 at 02:41
  • @X0R40: in practice, the memory for `i` will be set aside once at function entry. However, the code will behave *as though* a new instance is being created and destroyed in each iteration of the loop. – John Bode May 19 '15 at 11:52
0

The variable i will always be at 0 or 1 in this code; the break will never execute.

The variable i is declared in and is local to the while loop.

In the C language, a pair of braces can create a new scope that hides variables with the same name declared outside the scope.

This code:

void function(void)
{
    while(1)
    {
         int i = 0;
         i += 1;
         if(i == 500) break;
    }
}

should be changed to this:

void function(void)
{
    int i = 0;
    while(1)
    {
         i += 1;
         if(i == 500) break;
    }
}
A B
  • 4,068
  • 1
  • 20
  • 23