C语言函数中局部变量的返回

来源:互联网 发布:dede分类目录源码 编辑:程序博客网 时间:2024/05/18 00:59

http://blog.csdn.net/misskissc/article/details/10757975
http://blog.csdn.net/jackystudio/article/details/11523353

C/C++中,函数内部的一切变量(函数内部局部变量,形参 )都是在其被调用时才被分配内存单元。子函数运行结束时,所有局部变量的内存单元会被系统释放。形参和函数内部的局部变量的生命期和作用域都是在函数内部( static变量的生命期除外)。

在C中,函数被调用时的传参方式有两种形式:传值和传址。

传址的好处:

(1)能在函数内部通过实参地址间接地改变实参的值。

(2)当所传实参内容比较庞大时,传址只是复制了整个实参的地址过去,指针依据同一个地址访问实参变量。而传值就会将实参内容整个拷贝过去,形参会跟实参占一样大的内存,栈空间是有限的。当然了,在弱小的程序中,传址的这个优点不会被体现出来。

在函数中,可以随意的返回一个局部变量。但如果返回一个局部变量的地址(指针 ),编译器就会给出警告(编译器也不可能那么完美能够彻底的检查出段错误)。在函数内部返局部指针这的确是一个危险的操作。

Linux等的C语言中return返回值的机制为:将返回值存入eax寄存器中,然后系统再将eax中的值赋给变量(i)。

其实,只要遵守一句话即可:函数不能返回指向栈内存的指针!

  为什么?因为返回的都是值拷贝!

我们知道,局部变量的作用域是函数内部,函数一旦执行结束,栈上的局部变量会进行销毁,内存得到释放。因此,此时函数返回的是该局部变量的值拷贝,这是没有问题的。但是如果返回的是局部变量的地址,那么返回的只是该局部变量指针的拷贝,而随着函数运行结束,该拷贝指针所指向的栈内存已经被释放,那么指向一个未知区域就会导致调用的错误。

1.正确。最normal的情况。

int returnValue();int _tmain(int argc, _TCHAR* argv[]){    std::cout<<returnValue();    return 0;}char returnValue(){    int value=3;    return value;}

2.错误。最normal错误。虽然value被释放,但是它的值不一定会被清除,所以有时候你这么用看起来结果好像也是对的,但是隐患无穷。

int* returnValue();int _tmain(int argc, _TCHAR* argv[]){    std::cout<<*(returnValue());    return 0;}int* returnValue(){    int value=3;    return &value;}

3.正确。不用奇怪,“HelloJacky”是一个字符串常量,储存在只读数据段,return str只是返回了该字符串在只读数据段所在的首地址,当函数退出后,该字符串所在的内存不会被回收,所以是正常的。

char* returnValue();int _tmain(int argc, _TCHAR* argv[]){    std::cout<<returnValue();    return 0;}char* returnValue(){    char* str="HelloJacky";    return str;}

4.错误。这一回“HelloJacky”是栈内的局部变量,函数退出时内存被释放,因此返回栈内局部变量的地址是错误的。

char* returnValue();int _tmain(int argc, _TCHAR* argv[]){    std::cout<<returnValue();    return 0;}char* returnValue(){    char str[]="HelloJacky";    return str;}

5.正确。如果你非要返回一个局部变量的地址,那么加上static吧。

char* returnValue();int _tmain(int argc, _TCHAR* argv[]){    std::cout<<returnValue();    return 0;}char* returnValue(){    static char str[]="HelloJacky";    return str;}

6.错误,一样的,数组也不能作为函数的返回值,因为数组名其实是局部变量的首地址。

int* returnValue();int _tmain(int argc, _TCHAR* argv[]){    std::cout<<*(returnValue());    return 0;}int* returnValue(){    int value[3]={1,2,3};    return value;}

7.正确。加上static修饰符吧,那数组也可以返回了。

int* returnValue();int _tmain(int argc, _TCHAR* argv[]){    std::cout<<*(returnValue());    return 0;}int* returnValue(){    static int value[3]={1,2,3};    return value;}

8.正确。函数内申请空间,调用后释放空间,只是这样做的坏处就如上面所说接口不灵活。

char* newMemory(int size);int _tmain(int argc, _TCHAR* argv[]){    char* p=newMemory(2);    if(p!=NULL)    {        *p='a';    }    std::cout<<*p;    delete [] p;    return 0;}char* newMemory(int size){    char* p=NULL;    p=new char[size];    return p;}
原创粉丝点击