Why does it look like the declaration of i isn't popped off the stack at all?Because you never left the function. The stack pointer won’t be modified until you enter or exit a function.
And what you are seeing is undefined behavior. When it goes back into the loop it simply takes the value at the address of “i” and keeps working on it.
Not to confuse you further, but nothing really “leaves” the stack. It is just a series of addresses and a pointer to somewhere in them that gets shifted up and down as you enter/leave functions.
The pointer gets shifted but the data all over the stack is not changed when this happens. Through undefined behavior and hacks you can access values on the stack from the caller of your current function, for example. You can also modify values “ahead” of your current stack position and change data that the next function you call will use.
You are basically associating scopes with stacks. This is wrong. Scopes are a language constraint. Just because a variable goes out of scope does not mean the stack gets modified in any way (destructors can cause this to happen though). Nothing happens to “i” just because you leave the for-loop.