Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The reason why the address of <code>j</code> never changes is because the compiler allocates memory for <code>j</code> on the stack when the function is entered as opposed to when <code>j</code> comes into scope.</p> <p>As always, looking at some assembly code might help explain the concept. Take the following function:-</p> <pre><code>int foo(void) { int i=3; i++; { int j=2; i=j; } return i; } </code></pre> <p>gcc converts this to the following x86 assembly code:-</p> <pre><code>foo: pushl %ebp ; save stack base pointer movl %esp, %ebp ; set base pointer to old top of stack subl $8, %esp ; allocate memory for local variables movl $3, -4(%ebp) ; initialize i leal -4(%ebp), %eax ; move address of i into eax incl (%eax) ; increment i by 1 movl $2, -8(%ebp) ; initialize j movl -8(%ebp), %eax ; move j into accumulator movl %eax, -4(%ebp) ; set i to j movl -4(%ebp), %eax ; set the value of i as the function return value leave ; restore stack pointers ret ; return to caller </code></pre> <p>Let's walk through this assembly code. The first line saves the current stack base pointer so that it can be restored when the function exits, the second line sets the current top of the stack to be the new stack base pointer for this function.</p> <p>The third line is the one that allocates the memory on the stack for all the local variables. The instruction <code>subl $8, %esp</code> subtracts 8 from the current top of the stack pointer, the <code>esp</code> register. Stacks grow down in memory so this line of code actually increases the memory on the stack by 8 bytes. We have two integers in this function, <code>i</code> and <code>j</code>, each of which require 4 bytes, hence why it allocates 8 bytes.</p> <p>Line 4 initializes <code>i</code> to 3 by directly writing to an address on the stack. Lines 5 and 6 then load and increment <code>i</code>. Line 7 initializes <code>j</code> by writing the value 2 into the memory allocated for <code>j</code> on the stack. Note that when <code>j</code> came into scope at line 7 the assembly code did not adjust the stack to allocate memory for it, that had already been taken care of earlier.</p> <p>I'm sure it's obvious, but the reason why the compiler allocates the memory for all the local variables at the start of the function is because it is way more efficient to do so. Adjusting the stack each time a local variable went in or out of scope would result in a lot of unnecessary manipulations of the stack pointer for no gain.</p> <p>I'm sure you can work out what the rest of the assembly code does yourself, if not post a comment and I'll walk you through it.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload