这是源代码
#include <stdio.h>
#include <stdlib.h>
int *fun();
int main()
{
int *j;
j=fun();
printf("%d\n",*j);
printf("%d\n",*j);
return 0;
}
int *fun()
{
int k=35;
return &k;
}
输出 -
35
1637778
第一个printf()打印35,这是k的值,但是
在main()中,第二个printf打印一个垃圾值,而不是打印35.why?
答案 0 :(得分:5)
这里的问题是从fun
返回返回局部变量的地址。函数返回时该地址变为无效。第一次打电话给printf
时,你很幸运。
即使在fun
返回时技术上破坏了本地,C运行时也无法主动销毁它。因此,您首次使用*j
正在工作,因为本地的内存尚未被写入。 printf
的实现虽然可能只是通过在方法中使用自己的本地来编写它。因此,在*j
的第二次使用中,您指的是使用的本地printf
而不是k
。
为了完成这项工作,您需要返回一个指向长度超过fun
的值的地址。通常在C中,这是通过malloc
int *fun() {
int* pValue = malloc(sizeof(int));
*pValue = 23;
return pValue;
}
由于malloc
的回复仍然存在,直到您致电free
,这对printf
的多次使用都有效。一个问题是调用函数现在必须告诉程序何时完成fun
的重新调用。为此,请在第二次致电free
printf
j=fun();
printf("%d\n",*j);
printf("%d\n",*j);
free(j);
答案 1 :(得分:3)
程序调用未定义的行为。您不能返回指向自动局部变量的指针。 fun
返回后,变量不再存在。在这种情况下,您获得的结果可能是预期的或意外的
永远不会返回指向自动局部变量的指针
答案 2 :(得分:2)
您将返回存储在堆栈中的本地值。当你离开功能时,它会被删除。你得到了undefined behaviour
。
在你的情况下stack
在函数返回后没有改变,所以第一次得到正确的值。这在所有时间都不一样。
答案 3 :(得分:1)
两者都错了,因为您打印的值不再存在:只有在函数执行时,函数中存储int k
的内存才可以;你不能返回它的引用(指针),因为它将不再引用任何有意义的东西。
相反,以下内容可行:
int *fun()
{
static int k=35;
return &k;
}
静态关键字“表示”即使函数未运行,内存也必须“存活”,因此返回的指针将有效。
答案 4 :(得分:1)
正如其他人已经告诉过的,你的程序会调用未定义的行为。
这意味着,任何事情都可能发生在未定义行为的地方。
在您的情况下,会发生以下情况:返回位于堆栈上的变量的地址。从函数返回后,下一个函数调用可以 - 并将 - 重用该空间。
在函数调用错误地返回此地址和使用该值调用之间,没有任何反应 - 在您的情况下。请注意,即使在可能发生中断的系统上,以及信号能够中断正常程序运行的系统上,这可能也会有所不同。
第一个printf()
调用现在使用堆栈用于它自己的目的 - 也许它甚至是调用本身覆盖旧值。因此,第二个printf()
调用接收现在写入该内存的值。
在未定义的行为上,可能会发生任何事情。