在c中的函数中使用指针作为返回值

时间:2013-10-14 20:58:24

标签: c pointers

这是我的代码:

#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作为输出。否则显示垃圾值。任何想法?

3 个答案:

答案 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以获得正确的解释。