这是我的代码:
#include <stdio.h>
//returning a pointer
int *fun()
{
int i = 10;
//printf ("%u\n",i);
//printf ("%u\n",&i);
return &i;
}
int main()
{
int *p;
p = fun();
printf ("p = %u\n", p);
printf ("i = %u \n",*p);
return 0;
}
如果我删除了函数fun中的注释,那么main中的第二个printf显示10作为输出。否则显示垃圾值。任何想法?
答案 0 :(得分:3)
从不使用注释行i
。因此,根据您的优化程序,甚至可能永远不会分配i
。在函数中添加printf
时,现在使用变量,因此编译器会在堆栈帧上为i
分配内存(恰好在第二组printfs发生时没有回收) 。当然,您不能依赖于何时回收内存 - 但是下一次发生的函数调用很可能会覆盖fun()
堆栈帧。
如果将编译器设置为禁用代码优化,则可能会产生不同的结果。或者你可以尝试将变量设置为volatile
,它告诉编译器它不知道变量的所有用法,所以即使优化器说它不需要它也会分配它(它不会阻止变量的内存)在离开函数后被释放,它只会强制分配。
作为旁注,这个问题可以出现在嵌入式系统中,在该系统中,您有一个指向硬件寄存器的指针,该寄存器在设置时触发硬件操作(例如,您可能具有控制机器人手臂运动的硬件寄存器)。如果你没有声明指向该寄存器volatile
的指针,那么编译器可以优化你的任务,认为它从未使用过。
答案 1 :(得分:0)
当fun
返回时,i
超出范围,以便您现在返回的地址指向其他地址。尝试malloc()
一些记忆然后返回。当你完成它时不要忘记致电free()
:)
而且printf
中的第二个main
显示10
是一个纯粹的运气,因为您尚未将该空格/地址用于其他内容。
答案 2 :(得分:0)
由于@clcto在第一个注释中提到变量i
是函数本地的,并且在函数返回时它被取消分配。
现在为什么取消注释函数print
中的两个fun()
语句会使p的值为10?
这可能是由于许多原因可能取决于C
和您的系统的内部行为。但我的猜测是它正在发生,因为印刷品的运作方式
它保留了我知道的缓冲区。填充它然后在完全填满时将其打印到控制台。因此fun()中的前两个打印调用将i推送到缓冲区,该缓冲区尚未完全填充。所以当你从fun()返回时,i
可能没有被解除分配,因为缓冲区正在使用它(或者可能是我不确定的任何其他原因,但由于缓冲保留i
。)
为了支持我的猜测,我尝试在再次打印之前刷新缓冲区,现在它没有打印10.您可以看到输出here,修改后的代码如下:
#include <stdio.h>
//returning a pointer
int *fun()
{
int i = 10;
printf ("%u\n",i);
printf ("%u\n",&i);
return &i;
}
int main()
{
int *p;
p = fun();
fflush(stdout);
printf ("p = %u\n", p);
printf ("i = %u \n",*p);
return 0;
}
我认为我的猜测是错误的,因为@KayakDave发现了。它完全适合这种情况。请参考his answer以获得正确的解释。