实际发生的是:
所有局部变量都存储在堆栈中。
在调用 fun 之前,堆栈只包含 main 的 *a 变量,如:|int *a = undefined||
当 fun 被调用时,fun 的参数(即没有)、main 的地址和 fun 的局部变量都被添加到堆栈中:(|int *a = undefined| return to main | int a = 10 ||
还有帧指针但没关系)
fun 返回后,堆栈为|int *a = 2nd next stack var|| return to main | int a = 10 |
. 最后 2 个堆栈变量无效,但它们仍然存在。
当第一个 printf 被调用 printf 的参数时(以相反的顺序 *a then" %d"),在 *a 之后再次添加 printf 的返回地址和局部变量并覆盖旧值:
它首先变为 |int *a = 2nd next stack var| int a = 10 || int
a = 10 |
then |int *a = 2nd next stack var| int a = 10 | "%d" |
然后|int *a = 2nd next stack var| int a = 10 | "%d" | return to
main ||
和最后|int *a = 2nd next stack var| int a = 10 |
"%d" | return to main | local vars of printf ||
- 当第二个 printf 被调用时,*a 仍然指向第二个 bin,但是那个 bin 现在包含“%d”,它将显示为一个奇怪的数字
[编辑:]
fun2 不会覆盖堆栈上的 10,因为 gcc 在堆栈上保留了空箱,其中放置了被调用函数的参数。所以它不是|int *a = 2nd next stack var| return to main | int a = 10 |
我上面写的,而是更像|int *a = 4th next stack var | empty | empty | return to main | int a = 10 |
.
当 fun2 被调用时,它变为|int *a = 4th next stack var | empty | 5 | return to main | int a = 10 |
,并且 10 仍然没有被覆盖。
函数内int *a,b,c
的 无关紧要,因为它们没有分配值。
使用 gdb 您可以查看实际的堆栈(它向后增长):
玩乐前:
0xffffd454: 0x080496f0 0xffffd488 0x080484eb 0x00000001
noise (framepointer) address noise/empty bin
in main
在 fun 之后,在 fun2 及其参数之前:
0xffffd454: 0x0000000a 0xffffd488 0x08048441 0x00000001
a (framepointer) address noise/empty bin
in main
fun2之后:
0xffffd454: 0x0000000a 0xffffd488 0x08048451 0x00000005
a (framepointer) address argument
in main for fun2