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()
调用接收现在写入该内存的值
对于未定义的行为,任何事情都可能发生。正如其他人所说,您的程序调用未定义的行为
这意味着,任何事情都可能发生在