为什么第二个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
。 为此,请在第二次调用printf
后free
拨打电话
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()
调用接收现在写入该内存的值。
在未定义的行为上,任何事情都可能发生