[轉]函數如何正確的返回局部變量

       一般來說,函數是可以返回局部變量的。 局部變量的作用域只在函數內部,函數返回後,局部變量的內存已經釋放了。因此,如果函數返回的是局部變量的值,不涉及地址,程序不會出錯。但是如果返回的是局部變量的地址(指針)的話,程序運行後會出錯。因爲函數只是把指針複製後返回了,但是指針指向的內容已經被釋放了,這樣指針指向的就是不可預料的內容,調用就會出錯。準確的來說,函數不能通過返回指向棧內存的指針(注意這裏指的是棧,返回指向堆內存的指針是可以的)。下面舉幾個典型的例子來說明:

       1:

#include    
char *returnStr()   
{   
    char *p="hello world!";   
    return p;   
}   
int main()   
{   
    char *str;   
    str=returnStr();   
    printf("%s\n", str);   
    return 0;   
} 

       這個沒有任何問題,因爲"hello world!"是一個字符串常量,存放在只讀數據段,把該字符串常量存放的只讀數據段的首地址賦值給了指針,所以returnStr函數退出時,該字符串常量所在內存不會被回收,故能夠通過指針順利無誤的訪問。

       2:

    #include    
    char *returnStr()   
    {   
        char p[]="hello world!";   
        return p;   
    }   
    int main()   
    {   
        char *str;   
        str=returnStr();   
        printf("%s\n", str);   
        return 0;   
    }   

    "hello world!"是局部變量存放在棧中。當returnStr函數退出時,棧要清空,局部變量的內存也被清空了,所以這時的函數返回的是一個已被釋放的內存地址,所以有可能打印出來的是亂碼。
     3:
    int func()  
    {  
          int a;  
          ....  
          return a;    //允許  
    }                     
      
    int * func()  
    {  
          int a;  
          ....  
          return &a;    //無意義,不應該這樣做  
    }   

       局部變量也分局部自動變量和局部靜態變量,由於a返回的是值,因此返回一個局部變量是可以的,無論自動還是靜態,因爲這時候返回的是這個局部變量的值,但不應該返回指向局部自動變量的指針,因爲函數調用結束後該局部自動變量被拋棄,這個指針指向一個不再存在的對象,是無意義的。但可以返回指向局部靜態變量的指針,因爲靜態變量的生存期從定義起到程序結束。

     4:如果函數的返回值非要是一個局部變量的地址,那麼該局部變量一定要申明爲static類型。如下:
    #include    
    char *returnStr()   
    {   
        static char p[]="hello world!";   
        return p;   
    }   
    int main()   
    {   
        char *str;   
         str=returnStr();   
        printf("%s\n", str);   
      
        return 0;   
    }   

     5:數組是不能作爲函數的返回值的,原因是編譯器把數組名認爲是局部變量(數組)的地址。返回一個數組一般用返回指向這個數組的指針代替,而且這個指針不能指向一個自動數組,因爲函數結束後自動數組被拋棄,但可以返回一個指向靜態局部數組的指針,因爲靜態存儲期是從對象定義到程序結束的。如下:
int* func( void )  
{  
    static int a[10];  
    ........  
    return a;  
}
       6:返回指向堆內存的指針是可以的
char *GetMemory3(int num)  
{  
char *p = (char *)malloc(sizeof(char) * num);  
return p;  
}  
void Test3(void)  
{  
char *str = NULL;  
str = GetMemory3(100);  
strcpy(str, "hello");  
cout<< str << endl;  
free(str);  
} 
      程序在運行的時候用 malloc 申請任意多少的內存,程序員自己負責在何時用 free釋放內存。動態內存的生存期由程序員自己決定,使用非常靈活。

轉自CSDN,作者:haiwil     網址:http://blog.csdn.net/haiwil/article/details/6691854/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章