指针返回地址

时间:2015-12-11 04:50:48

标签: c function pointers scope

当变量在某个块内定义时,它会在到达块的末尾时被销毁。

所以从下面的程序我预计会有某种警告

#include<stdio.h>
int *fun()
{
    int i=10;
    return &i;
}

int main(void)
{
    int *p=fun();
    return 0;
}

我期待一个警告,因为我试图返回局部变量i的地址,当控件退出范围时将被销毁

但是如果我将值变量i存储在某个整数指针中,然后从像这样的乐趣中返回值

#include<stdio.h>
int *fun()
{
    int i=10,*p;
    p=&i;
    return p;
}

int main(void)
{
    int *p=fun();
    return 0;
}

为什么我没有得到任何警告?

4 个答案:

答案 0 :(得分:2)

  • 只有在直接返回本地变量的地址时,编译器才会发出警告。
  • 如果返回地址指针,则不会发出警告。
  • 不检查地址指针是否分配了局部变量。

重复:Return address of local variable in C

为什么两个程序都会以未定义的行为重现:https://www.fayewilliams.com/2015/06/30/a-challenge-discussion-returning-pointers-to-local-variables/

答案 1 :(得分:0)

编译器仅在前一个程序中而不是第二个程序中发出警告,因为从技术上讲,您不返回局部变量的地址。

编译器如何查看事物,它只能查看语法产生的静态计算警告。

另外,刚刚发现:Return address of local variable in C

答案 2 :(得分:0)

会收到警告:

warning: function returns address of local variable [-Wreturn-local-addr]

必须使用命令行选项-Wall进行编译。我还建议使用-Werror。使用这两个选项始终。你已经警告: - )

另外,请注意,该值并非真正已销毁 [如在Java中]。它仍然存在于返回的内存位置,它是fun堆栈帧的一部分。对于简短(即不可预测/未定义)的时间量,它将保持不变。

只是如果你调用任何其他函数,那个函数的堆栈框架将处于同一个地址,无论它做什么都会[可能]使fun的i的值看起来像垃圾。

例如:

fun stack frame:
    int i;          // offset 0x00
    int *p;         // offset 0x04

fn2 stack frame:
    double q;       // offset 0x00
    int x;          // offset 0x08
    int j;          // offset 0x0C

因此,在致电fun后,您拨打fn2并将q设置为123.7。从fn2返回后,q的前四个字节覆盖了fun的{​​{1}}所占据的空间。因此,i

的“垃圾”值

答案 3 :(得分:0)

这是因为在C中,因为变量超出范围并不意味着系统像java一样释放内存。在C中如果你创建一个变量并设置一个指向该变量的指针,那么只要你有指向该变量的指针就可以获得该值并进行修改。这是打印p所持有的值所需要做的事情。

#include<stdio.h>
int *fun()
{
    int num=2;//this sets some memory address equal to 2
    int *p=&num; //this sets some memory address equal to
                 //the memory address of num
    return p; //this returns a "pointer" to the value
              //of num
}

int main(void)
{
    int *p=fun();
    printf("num equals: %d\n",*p); //need star to get to the value of num
                      //if you tried to print p by itself it would work
                      //but it would be a memory address which
                      //means nothing to the program
    return 0;
} //output is "num equals: 2"