關於子函數內存分配和鏈表的一點隨筆

子函數中用malloc給指針分配空間,到主函數中就沒了。那麼怎麼在子函數中分配空間?
答:返回一個指針,或傳遞一個指向指針的指針爲參數

    char *GetMemory(int num)
    {
        char *p = (char *)malloc(sizeof(char) * num);
        return p;
    }
    調用:
    char *str=NULL;
    str = Getmemery(3);

    void GetMemory2(char **p, int num)
    {
        *p = (char *)malloc(sizeof(char) * num);
     }
    調用:
    char *str=NULL;
    Getmemery2(&str, 3);


分析:
分析一下這個爲什麼會錯了。


(1)void Getmemery(char *p)


(2)char *str=NULL;


(3)Getmemery(str);


1中子程序的形參是一個指針,然後很自然會想到2,3中的調用方式,本來的想法是用malloc分配內存,然後修改傳入的指針變量,那麼最後就根據 通過 strcpy(str,"hello world"); 就可以向分配的內存裏面寫數據了。一切都是那樣流暢,對,因爲這個用法平時用習慣了,所以根本不會去考慮正確性。


然而,這裏就出問題了。首先,Getmemery(str) 傳遞的是 srt指針的地址,這個沒有問題,C不同於C++,參數是通過傳遞的,而不是通過引用。也就是說,實際參數 srt 先自己copy一份,然後傳遞給形式參數 *P接收,這個C語言的指針的時候已經強調多次了,但是自己還是錯了啊,哈哈。


然後,在子程序裏面,如果通過 *P 那麼訪問到的將是 *str的內容,這是等價的。但是,本程序一個致命的錯誤,非常隱蔽,那是子程序企圖修改 p 的內容,而不是 *p 的內容!! 這個錯誤找了我很久終於給揪出來了。修改了 p 的值是沒有意義的,這個值是形式參數,並不會返回任何的東西,而 *p 則是通過p的地址直接訪問需要的變量,這是不同的用法。所以說白了,void Getmemery(char *p) 執行之後並沒有改變任何的東西,str的值並沒有修改過,保持NULL,所以訪問 *0 地址會被操作系統禁止,得到一個錯誤。


解決辦法,是用2重指針。目的是要修改指針的地址,但是按照上面的分析,我們並不能去修改,但是我們可以用2重指針,將*str的地址值str,用2重指針來改變。
void Getmemery(void **p)
{
 *p=(void **)malloc(100);
}


子程序修改爲這個樣子,出入的參數也得修改


char *str=NULL;
Getmemery(&str);


那麼可以這樣理解,因爲形參是2重指針,所以 p 對應 &str ,*P 對應 str,之前說了,我們的目的是要修改 str的值,所以很自然,我們用 *p = xxx 這樣的形式去修改了。


這樣得到的程序就正確了。

關於鏈表的一些知識

詳見:http://blog.csdn.net/zhenyusoso/article/details/6092843

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