以下是代码
守则:
#include <stdio.h>
int * num(void);
int main(void)
{
int * num2;
num2 =num();
printf("%d\n" , *num2);
return 0;
}
int * num(void)
{
int num = 20;
return #
}
问题:
我们知道,函数num
是函数num()
的本地函数,所以在这段代码中我尝试将函数中变量num
的地址返回给调用它的函数,即main()
。
之后,我只使用解除引用运算符来提取特定num
变量的值,并将其打印在main()
函数中。
有一件事我很困惑。我记得我读过一本关于javascript的书,提到变量生命周期在函数内,这意味着在函数完成执行其指令并将控制权传递给调用它的函数之后,函数中每个变量的值将是干净的out(垃圾收集器)。但为什么在这段代码中我的main()
函数仍然可以指向该特定内存地址的值?
答案 0 :(得分:6)
您可以看到变量值的原因是因为堆栈的工作原理。在输入函数num
时,有效地移动指针(堆栈指针)以为函数的本地存储添加空间。退出函数时,堆栈指针有效地向后移动,这意味着下一个函数调用将覆盖前一个函数调用中使用的堆栈存储。然而,在被覆盖之前,价值存在于一种不确定的状态。它实际上仍然在内存中,但可能随时被覆盖。那里存在的实际价值可能是也可能不是。这就是为什么像上面那样做被称为未定义的行为。
基本上......不要这样做。
答案 1 :(得分:1)
只是添加@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 #
}
很有可能你不会得到“20”作为输出(也有可能终止程序) 另外,在编译时,编译器会警告您“警告:函数返回局部变量的地址”:)
答案 2 :(得分:0)
返回指向局部变量的指针是不对的。当该函数返回时,变量num
被释放,并且C运行库可以将该内存地址用于另一个值。返回的指针现在无效,因为它指向未分配的内存区域,并且如果使用则将调用未定义的行为。未定义的行为意味着它可能会或可能不会执行您想要的操作。在某些情况下,程序会崩溃,在其他情况下它可能会起作用。为什么它在这种情况下有效是因为该部分内存仍将保持值20
。在重新分配后,C运行时不会用0来填充内存的那部分。