What actually happens is:
All local variables are stored on the stack.
Before the call to fun, the stack contains only the *a variable of main, like: |int *a = undefined||
When fun is called, the parameters to fun (i.e. none), the address to main and the local variables of fun are added to the stack: |int *a = undefined| return to main | int a = 10 ||
(there is also the frame pointer but that doesn't matter)
After fun returns, the stack is |int *a = 2nd next stack var|| return to main | int a = 10 |
. The last 2 stack variables are invalid, but they are still there.
When the first printf is called the parameters to printf (in inverse order *a then" %d"), the return address and the local variables of printf are added again after *a and override the old values:
It first becomes |int *a = 2nd next stack var| int a = 10 || int
a = 10 |
then |int *a = 2nd next stack var| int a = 10 | "%d" |
then |int *a = 2nd next stack var| int a = 10 | "%d" | return to
main ||
and finally |int *a = 2nd next stack var| int a = 10 |
"%d" | return to main | local vars of printf ||
- When the second printf is called, *a still points to the second bin, but that one contains now "%d", which will appear as a strange number
[edit:]
The fun2 does not override the 10 on the stack, because gcc reserves empty bins on the stack, where the arguments of called functions are put. So it is not |int *a = 2nd next stack var| return to main | int a = 10 |
as I wrote above, but more like |int *a = 4th next stack var | empty | empty | return to main | int a = 10 |
.
When fun2 is called, it becomes |int *a = 4th next stack var | empty | 5 | return to main | int a = 10 |
, and the 10 is still not overriden.
The int *a,b,c
within the function do not matter, since they do not have a value assigned.
With gdb you can look at the actual stack (it grows backward):
Before fun:
0xffffd454: 0x080496f0 0xffffd488 0x080484eb 0x00000001
noise (framepointer) address noise/empty bin
in main
After fun, before fun2 and its arguments:
0xffffd454: 0x0000000a 0xffffd488 0x08048441 0x00000001
a (framepointer) address noise/empty bin
in main
After fun2:
0xffffd454: 0x0000000a 0xffffd488 0x08048451 0x00000005
a (framepointer) address argument
in main for fun2