使用指針做函數返回值和指針(棧內存與堆內存的函數形式使用)

一、使用指針做函數返回值:

 

1、當使用指針做爲函數的返回值時,主函數處的char *p;將獲得調用函數char *pf;的值,即一個地址值,如oxAE72。此時需要我們注意的是該地址值所指向的空間是否存在(即已向操作系統聲明註冊,不會被釋放,即可能被其他操作修改)

 

2、使用棧內存返回指針是明顯錯誤的,因爲棧內存將在調用結束後自動釋放,從而主函數使用該地址空間將很危險。

   例如:

            char* GetMemory()

            {

                        char p[] = "hi";

                        return p;

            }

           

            void main()

            {

                        char *str = GetMemory();           //出錯得到一塊已釋放的內存

                        printf(str);

            }

 

3、使用堆內存返回指針是正確的,但是注意可能產生內存泄露問題,在使用完畢後主函數中釋放該段內存。

   例如:

            char* GetMemory()

            {

                        char *p = new char[100];

                        return p;

            }

 

            void main()

            {

                        char *str = GetMemory();

                        delete [] str;       //防止內存泄露!

            }

 

二、使用指針做函數參數:

 

1、有的情況下我們可能需要需要在調用函數中分配內存,而在主函數中使用,而針對的指針此時爲函數的參數。此時應注意形參與實參的問題,因爲在C語言中,形參只是繼承了實參的值,是另外一個量(ps:返回值也是同理,傳遞了一個地址值(指針)或實數值),形參的改變並不能引起實參的改變。

 

2、直接使用形參分配內存的方式顯然是錯誤的,因爲實參的值並不會改變,如下則實參一直爲NULL:

            void GetMemory(char* p)

            {

                        char *p = new char[100];

            }

 

            void main()

            {

                        char *str;

                        GetMemory(str);

                        strcpy(str, "hi"); //出錯! str = NULL!

            }

 

3、由於通過指針是可以傳值的,因爲此時該指針的地址是在主函數中申請的棧內存,我們通過指針對該棧內存進行操作,從而改變了實參的值。

            void Change(char *p)

            {

                        *p = 'b';

            }

 

            void main()

            {

                        char a = 'a';

                        char* p = &a;

                        Change(p);

                        printf("%c"n", a);           //a改變!

            }

 

4、根據上述的啓發,我們也可以採用指向指針的指針來進行在調用函數中申請,在主函數中應用。如下:假設a的地址爲ox23,內容爲'a';而str的地址是ox46,內容爲ox23;而pstr的地址是ox79,內容爲ox46

   我們通過調用函數GetMemory,從而將pstr的內容賦給了p,此時p = ox46。通過對*p(ox23)的操作,即將內存地址爲ox23之中的值改爲char[100]的首地址,從而完成了對char* str地址的分配。

            void GetMemory(char** p)

            {

                        char *p = new char[100];

            }

 

            void main()

            {

                        char a = 'a';

                        char* str = &a;

                        char** pstr = &str;

                        GetMemory(pstr);

                        strcpy(str, "hi");

            }

5、注意指針的釋放問題,可能形成懸浮指針。

   當我們釋放掉一個指針p後,只是告訴操作系統該段內存可以被其他程序使用,而該指針p的地址值(ox23)仍然存在。如果再次給這塊地址賦值是危險的,應該將p指針置爲NULL

   調用函數刪除主函數中的內存塊時,雖然可以通過地址傳遞直接刪除,但由於無法對該指針賦值(形參不能傳值),可能造成懸浮指針,所以此時也應該採用指向指針的指針的形參。例如:

            void MemoryFree(char** p)

            {

                        delete *p;

                        *p = NULL;

            }

            void main()

            {

                        char *str = new char[100];

                        char *pstr = &str;

                        MemoryFree(pstr);        

            }

發佈了16 篇原創文章 · 獲贊 2 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章