本文介绍了为什么局部变量没有超出范围?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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()中的局部变量var2un()运行时被放在与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的地址。

这篇关于为什么局部变量没有超出范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-14 08:04