当变量在某个块内定义时,它会在到达块的末尾时被销毁。
所以从下面的程序我预计会有某种警告
#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;
}
为什么我没有得到任何警告?
答案 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)
编译器仅在前一个程序中而不是第二个程序中发出警告,因为从技术上讲,您不返回局部变量的地址。
编译器如何查看事物,它只能查看语法产生的静态计算警告。
答案 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=# //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"