x
是局部变量,执行结束后应超出范围fun()
。
它的地址通过返回的指针和全局指针提供p
,该指针指向不再有效的对象。但仍然输出的是5
。
为什么?
#include <stdio.h>
int *p = NULL;
int *fun() {
int x = 5;
p = &x;
return p;
}
// Driver Code
int main() {
printf("%d", *(fun()));
return 0;
}
局部变量在堆栈中分配。当您从main()调用fun()时,堆栈显示如下:
+---------------+ <---- Stack pointer
| local var x |
+---------------+ <---- Address of 'x'
| Return addr |
| in main() |
+---------------+
|Local vars of |
| main() |
+---------------+
| ... |
+---------------+
当您返回main()时,将从堆栈中弹出局部变量,返回的地址和参数。但是不会清除堆栈(顺便说一句,它将消耗过多的CPU!)。因此,只有堆栈指针移动:
+---------------+
| local var x |
+---------------+ <---- Address of 'x'
| Return addr |
| in main() |
+---------------+ <---- Stack pointer moved with the pops
|Local vars of |
| main() |
+---------------+
| ... |
+---------------+
即使未清除堆栈指针上方的所有内容,也将视为无效。所以,这就是为什么你足够幸运得到的值x
在main()的函数。
但是,假设您在fun()之后立即调用另一个函数:
#include<stdio.h>
#include<string.h>
int *p = NULL;
void fun2()
{
int var = 18;
int var2 = 43;
printf("fun2() called, var@%p=%d, var2@%p=%d\n", &var, var, &var2, var2);
}
int *fun()
{
int x = 5;
p= &x;
return p;
}
// Driver Code
int main(int argc, char *argv[])
{
int *px;
px = fun();
printf("x@%p=%d\n", px, *px);
if (argc != 1) {
fun2();
}
printf("x@%p=%d\n", px, *px);
return 0;
}
当程序不调用fun2()时,它的行为与您相同,但我添加了以下地址的显示x
:
$ gcc try.c -o try
$ ./try
x@0x7ffd5beb5f04=5
当程序传递任何参数时,我们在fun()之后调用fun2(),并在调用fun2()之前和之后显示:x
$ ./try any_param
x@0x7ffeadacc084=5
fun2() called, var@0x7ffeadacc080=18, var2@0x7ffeadacc084=43
x@0x7ffeadacc084=43
我们可以看到,价值x
在调用后更改为43 FUN2() ,因为局部变量var2
在FUN2()已经把在同一地点x
时的乐趣()正在运行。因此,0x7ffeadacc084
堆栈中的相同地址当然是其新值43x
实际上是的值var2
。
这是调用fun2()之后堆栈的样子( _fun()的先前数据已被fun2()的数据覆盖):
+---------------+
|local var var |
+---------------+ <---- Address of 'var' = 0x7ffeadacc080
|local var var2 |
+---------------+ <---- Address of 'var2' = 0x7ffeadacc084
| Return addr |
| in main() |
+---------------+ <---- Stack pointer moved with the pops
|Local vars of |
| main() |
+---------------+
| ... |
+---------------+
PS:堆栈从高地址增长到低地址。因此,var
位于比的地址低的地址var2
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句