为什么第二个printf打印垃圾值

时间:2014-01-05 17:01:46

标签: c garbage

这是源代码

#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?

5 个答案:

答案 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()调用接收现在写入该内存的值。

在未定义的行为上,可能会发生任何事情。