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

C 为什么第二个printf打印垃圾值,c,garbage,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; } 第一个printf()打印35,这是k的值,但是 在m

这是源代码

#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;
}
第一个printf()打印35,这是k的值,但是


在main()中,第二个printf打印一个垃圾值,而不是打印35。为什么?

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

永远不要返回指向自动局部变量的指针

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

切勿返回指向自动局部变量的指针

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

相反,以下方法可行:

int *fun()
{
  static int k=35;

  return &k;
}

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

两者都是错误的,因为您打印了一个不再存在的值:函数中存储
int k
的内存只有在函数执行时才正常;您不能返回对它的引用(指针),因为它将不再引用任何有意义的内容

相反,以下方法可行:

int *fun()
{
  static int k=35;

  return &k;
}

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

这里的问题是
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
完成。第二次调用
printf

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

这里的问题是从
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
完成。第二次调用
printf

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

您将返回存储在堆栈中的本地值。当您退出功能时,它会被删除。您将获得
未定义的行为


在您的例子中,
堆栈
在函数返回后没有改变,所以第一次得到正确的值。这在任何时候都是不同的。

您返回的是存储在堆栈中的本地值。当您退出功能时,它会被删除。您将获得
未定义的行为


在您的例子中,
堆栈
在函数返回后没有改变,所以第一次得到正确的值。这在任何时候都是不同的。

正如其他人所说的,您的程序调用未定义的行为

这意味着,如果行为没有定义,任何事情都可能发生

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

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

第一个
printf()
调用现在将堆栈用于自己的目的——甚至可能是调用本身覆盖了旧值。因此,第二个
printf()
调用接收现在写入该内存的值


对于未定义的行为,任何事情都可能发生。

正如其他人所说,您的程序调用未定义的行为

这意味着,任何事情都可能发生在