本文介绍了为什么局部变量没有超出范围?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
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() |
+---------------+
| ... |
+---------------+
堆栈指针上方的所有内容都被视为无效,即使它没有被清除。因此,您很幸运地在main()函数中获得了x
的值。但假设您在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
", &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
", px, *px);
if (argc != 1) {
fun2();
}
printf("x@%p=%d
", 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
我们可以看到,在调用fun2()后,x
的值被更改为43,因为fun2()中的局部变量var2
在un()运行时被放在与x
相同的位置。因此,堆栈中的相同地址0x7ffeadacc084
,当然还有x
的新值43,它实际上是var2
的值。
调用fun2()后的堆栈情况如下(原来的_un()数据已被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
的地址。
这篇关于为什么局部变量没有超出范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!