为什么gcc在返回指向局部变量的指针时抛出警告而不是在返回局部变量时抛出警告?

时间:2011-11-18 14:53:11

标签: c gcc compiler-construction operating-system

请参阅下面的代码示例。 函数return (&i)中的语句fun_ret_loc_ptr()返回一个警告:“函数返回局部变量的地址”。另一方面,函数return a中的语句fun_ret_loc_var()不会这样做。

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

int fun_ret_loc_var()
{
   int a = 20;
   return a;
}

int main()
{
   printf("val frm local ptr = %d\n", *fun_ret_loc_ptr());
   printf("val frm local var = %d\n", fun_ret_loc_var());
}

据我所知,在第一个函数中,返回的地址(return (&i);)被引用到作为与函数fun_ret_loc_ptr()对应的堆栈帧的一部分的内存位置。一旦此函数返回,堆栈帧(激活记录)将被销毁。同样的事情应该适用于函数return a;中的变量'a'(fun_ret_loc_var())。即使它被返回,当它在main中使用时,对应于'a'的内存也会死亡。

从“return”声明的功能角度来看,为什么会出现这种差异?

4 个答案:

答案 0 :(得分:5)

按值返回变量会复制它,因此从函数返回后使用它是安全的。

将引用(或指针)返回到局部变量是不安全的(因为从函数返回后引用/指针不再有效)。

现在,如果程序似乎做你期望的事情,那纯属巧合。这称为 Undefined Behaviour 。事实上,结果可能是任何事情(从你的车开始,直到未来三周仔细地做午餐。它只是未定义

答案 1 :(得分:2)

你在帖子的最后很好地解释了这个解释。你唯一的“错误”就是在函数调用结束时变量“死”。确实它确实死了,但是返回了a的副本,而不是函数堆栈中的a。因此,访问该函数的返回值没有问题。

答案 2 :(得分:1)

你可以想象通过值或参考传递参数的类比。

在这里,您可以通过引用或值返回值。如果按值返回值,则该值在调用者中可用。如果通过引用返回值,则将值的引用返回给调用者。要访问该值,调用者必须取消引用,但引用不再指向任何有效值。

答案 3 :(得分:0)

函数不返回变量;他们返回。值是否来自局部变量是无关紧要的;即使它没有,它来自一个“本地表达”(我的术语),其寿命甚至比局部变量的短。将指针返回到本地(假设它是自动的,而不是静态的)变量的问题是指针的无效,并且在函数返回后对它的任何使用都会导致未定义的行为。