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

这是源代码

#include  #include  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.为什么?

这里的问题是从fun返回返回局部变量的地址。 函数返回时该地址无效。 第一次打电话给printf你很幸运。

即使本地在fun返回时在技术上被破坏,C运行时也不会主动销毁它。 因此,你第一次使用*j有效的,因为本地的内存尚未被写入。 printf的实现可能只是通过在方法中使用自己的locals来编写它。 因此,在第二次使用*j你指的是使用的本地printf而不是k

为了完成这项工作,您需要返回一个地址,该地址指向一个比fun更长寿的值。 通常在C中,这是通过malloc实现的

 int *fun() { int* pValue = malloc(sizeof(int)); *pValue = 23; return pValue; } 

因为malloc的返回一直存在,直到你调用free这对printf多次使用都是有效的。 一个问题是调用函数现在必须告诉程序何时完成重新调用的fun 。 为此,请在第二次调用printffree拨打电话

 j=fun(); printf("%d\n",*j); printf("%d\n",*j); free(j); 

程序调用未定义的行为 。 您不能返回指向自动局部变量的指针。 一旦fun回归,变量就不再存在。 在这种情况下,您获得的结果可能是预期的或意外的。
永远不要返回指向自动局部变量的指针

您将返回存储在堆栈中的本地值。 当你离开function时,它会被删除。 你得到了undefined behaviour

在你的情况下,函数返回后stack没有改变,所以第一次得到正确的值。 这在任何时候都不一样。

两者都是错误的,因为你打印的值不再存在:只有在函数执行时才能在函数中存储int k的内存; 你不能返回它的引用(指针),因为它将不再引用任何有意义的东西。

相反,以下内容可行:

 int *fun() { static int k=35; return &k; } 

static关键字“表示”即使函数未运行,内存也必须“存活”,因此返回的指针将有效。

正如其他人已经告诉过的,你的程序会调用未定义的行为。

这意味着,任何事情都可能发生在未定义行为的地方。

在您的情况下,会发生以下情况:返回位于堆栈上的变量的地址。 从函数返回后,下一个函数调用可以 – 并将 – 重用该空间。

在函数调用错误地返回此地址和使用该值调用之间,没有任何反应 – 在您的情况下。 请注意,即使这种情况在可能发生中断的系统上也可能不同,以及在信号能够中断正常程序运行的系统上也是如此。

第一个printf()调用现在使用堆栈用于它自己的目的 – 也许它甚至是调用本身覆盖旧值。 所以第二个printf()调用接收现在写入该内存的值。

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

    Interesting Posts