函数中使用的内存何时可用??(C编程)
下面是代码 守则:函数中使用的内存何时可用??(C编程),c,variables,pointers,memory-address,C,Variables,Pointers,Memory Address,下面是代码 守则: #包括 int*num(无效); 内部主(空) { int*num2; num2=num(); printf(“%d\n”,*num2); 返回0; } int*num(无效) { int num=20; return# } 问题是: 我们知道,函数num是其函数num()的本地函数,因此在这段代码中,我尝试将函数中变量num的地址返回给调用它的函数,即main() 之后,我只需使用解引用操作符提取特定num变量的值,并在main()函数中打印出来 有一件事我很困惑
#包括
int*num(无效);
内部主(空)
{
int*num2;
num2=num();
printf(“%d\n”,*num2);
返回0;
}
int*num(无效)
{
int num=20;
return#
}
问题是:
num
是其函数num()
的本地函数,因此在这段代码中,我尝试将函数中变量num
的地址返回给调用它的函数,即main()
num
变量的值,并在main()
函数中打印出来返回指向局部变量的指针是不正确的。变量
num
在该函数返回且该内存地址可供C运行时用于另一个值时释放。返回的指针现在无效,因为它指向未分配的内存区域,如果使用,将调用未定义的行为。未定义的行为意味着它可能做或不做你想做的事情。在某些情况下,程序会崩溃,在另一种情况下,它可能会工作。它之所以在这种情况下工作,是因为该部分内存仍将保留值20
。取消分配后,C运行时不会用0填充该部分内存。可以看到变量值的原因在于堆栈的工作方式。当您输入函数num
时,一个指针(堆栈指针)将被移动,以便为函数的本地存储添加空间。退出函数时,堆栈指针将向后移动,这意味着下一个函数调用将覆盖上一个函数调用中使用的堆栈存储。但是,在被覆盖之前,该值存在于某种模糊状态中。它实际上仍然存在于内存中,但随时可能被覆盖。实际值的存在可能存在,也可能不存在。这就是为什么像上面那样做被称为未定义行为的原因
基本上。。。不要这样做。只是在@Goz解释得很好的基础上增加了一些内容。请尝试以下代码:
#include <stdio.h>
int * num(void);
int fib(int n)
{
if( 0 == n || 1 == n )
return n;
return fib(n-1) + fib(n-2);
}
int main(void)
{
int * num2;
num2 =num();
(void)fib(7);
printf("%d\n" , *num2);
return 0;
}
int * num(void)
{
int num = 20;
return #
}
#包括
int*num(无效);
整数fib(整数n)
{
如果(0==n | | 1==n)
返回n;
返回fib(n-1)+fib(n-2);
}
内部主(空)
{
int*num2;
num2=num();
(无效)fib(7);
printf(“%d\n”,*num2);
返回0;
}
int*num(无效)
{
int num=20;
return&num;
}
很有可能您不会得到“20”作为输出(也有可能程序终止)
此外,在编译时,编译器会警告您“警告:函数返回局部变量的地址”:)main中的代码仍然可以指向该内存地址的原因是,与JavaScript不同,C中没有垃圾收集器。这一点与下面的4个答案相矛盾。我不知道你在看哪一个答案,但你在考虑动态范围吗?动态范围从堆栈中清除对象,这是与垃圾收集不同的概念。
#include <stdio.h>
int * num(void);
int fib(int n)
{
if( 0 == n || 1 == n )
return n;
return fib(n-1) + fib(n-2);
}
int main(void)
{
int * num2;
num2 =num();
(void)fib(7);
printf("%d\n" , *num2);
return 0;
}
int * num(void)
{
int num = 20;
return #
}