C - Why variables created in a loop have the same memory address?

Viewed 1227

Just a simple example of my problem:

while(condition){
    int number = 0;
    printf("%p", &number);
}

That variable will always be in the same memory address. Why?

And what's the real difference between declaring it inside or outside the loop then?

Would I need to malloc the variable every iteration to get different addresses?

5 Answers

That variable will always be in the same memory address. Why?

It's not required to, but your code is so simple that it probably will be across all platforms. Specifically, because it's stored on the stack, it's always in the same place relative to your stack pointer. Keep in mind you're not allocating memory here (no new or malloc), you're just naming existing (stack-relative) memory.

And what's the real difference between declaring it inside or outside the loop then?

In this case, scope. The variable doesn't exist outside the braces where it lives in. Also outside of the braces, another variable can take its place if it fits in memory and the compiler chooses to do this.

Would I need to malloc the variable every iteration to get different addresses?

Yes, but I have yet to see a good use of malloc to allocate space for an int that a simple stack variable or a standard collection wouldn't do better.

That variable will always be in the same memory address. Why?

The compiler decides where the variable should be, given the operating system constraints, it's much more efficient to maintain the variable at the same address than having it relocated at every iteration, but this could, theoretically, happen.

You can't rely on it being in the same address every time.

And what's the real difference between declaring it inside or outside the loop then?

The difference is lifetime of the variable, if declared within the loop it will only exist inside the loop, you can't access it after the loop ends.

When execution of the block ends the lifetime of the object ends and it can no longer be accessed.

Would I need to malloc the variable every iteration to get different addresses?

malloc is an expensive operation, it does not make much sense to malloc the variable at every iteration, that said, again, the compiler decides where the memory for it is allocated, it may very well be at the same address or not.

Once again you can't rely on the variable location in the previous iteration to assert where it will be on the next one.

There is a difference in the the variables are stored, allocated variables will be on the heap, as opposed to the stack like in the previous case.

It is being put into the same memory address to save memory.

The only real difference between declaring it within and without the loop is that the variable will no longer be within scope outside the loop if it was declared within the loop.

You would have to use malloc to get a different address each time. Also, you would have to leave the frees until after all the mallocs to get this guarantee.

That variable will always be in the same memory address. Why?

The object that number designates has auto storage duration and only exists for the lifetime of the loop body, so logically speaking a new instance is created and destroyed on each loop iteration.

Practically speaking, it's easier to just re-use the same memory location for each loop iteration, which is what most (if not all) C compilers do. It's just not guaranteed to retain its last value from one iteration to the next (especially if you initialize it each iteration).

And what's the real difference between declaring it inside or outside the loop then?

The lifetime of the object (the period of program execution where storage is guaranteed to be reserved for it) changes from the body of the loop to the body of the function. The scope of the identifier (the region of program text where the identifier is visible) changes from the body of the loop to the body of the entire function.

Again, practically speaking, most compilers will allocate stack space for auto objects that are in blocks at function entry - for example, given the code

void foo( void )
{
  int bar;
  while ( bar = 0; bar < 10; bar++ )
  {
    int bletch = 2 * bar;
    ...
  }
}

most compilers will generate instructions to reserve stack space for both bar and bletch at function entry, rather than waiting until loop entry to reserve space for bletch. It's just easier to set the stack pointer once and get it over with. Storage is guaranteed to be reserved for bletch over the lifetime of the loop body, but there's nothing in the language definition that says you can't reserve it before then.

However, if you have a situation like this:

void foo( void )
{
  int bar;
  while ( bar = 0; bar < 10; bar++ )
  {
    if ( bar % 2 == 0 ) // bar is even
    {
      int bletch = 2 * bar;
      ...
    }
    else
    {
      int blurga = 3 * bar + 1;
      ...
    }
  }

bletch and blurga cannot exist at the same time, so the compiler may only allocate space for one additional int object, and that same space will be used for either bletch or blurga depending on the value of bar.

There are compilers that, despite you declaring the variable in the inner loop, just allocate them at the entry to the function block.

Modern compilers tend to allocate all memory for local variables in a single shot at function entry, so that only represents a single stack pointer move, against several push pop instructions to get the same result.

Despite of that, there's another issue you have not considered. The variable in the inner loop is not visible outside the loop, and the memory used by it can be used for a different variable outside. You know that the memory address is always the same... but you don't know when you are out of scope if any of the other variables you use for a different thing are given the same address by the compiler (that's perfectly legal, as your variable is automatic, and so, it ceases to exist as soon as you get out of the block (the pair of curly brackets you put around the loop)

Related