工做中優化一段代碼,代碼中有一大段分配堆內存的內容,我以爲這段代碼太長了,更適合放在子函數裏面。函數
我把指針做爲參數,而後在子函數中malloc分配內存,結果出現了問題,函數結束後,以參數傳進來的指針並無指向分配的內存。優化
好比說:spa
int fun(unsigned char *p, unsigned char **p1) { p = (unsigned char *)malloc(N * sizeof(unsigned char)); if (NULL == p) return -1; // 給二維指針p1分配 p1 = fun_set_p1(); if (NULL == p1) { free(p); return -1; } return 0; } unsigned char *p; unsigned char **p1 fun(p, p1);
運行完fun後,*p和**p1並無發生變化。指針
指針做爲參數不是傳的是地址嗎?怎麼沒變化呢?code
其實這樣想是一種誤區,其實指針做爲參數也是值傳遞,在函數中將參數複製一份而已。指向的是同一塊內存地址。假設參數傳的是int *p,函數內copy的j是int *p_1。在函數中操做*p_1,例如*p_1 = 1, 則p_1所指向的內容就變成了1.,因爲他們是指向同一塊地址,因此即便他們不是同一個指針*p所指向的內存也會被改變。blog
但若是讓p_1指向其餘的內存地址,則因爲是值傳遞,p並不會所以而改變。內存
其實反彙編能夠看出,參數的傳遞其實就是將變量放入新開闢的函數棧空間,也就是我說的「copy一份」,函數中再對棧空間裏的內容操做,這就是值傳遞的本質。class
因此這種狀況該怎麼辦呢?變量
一種狀況是函數 返回 指向新申請內存的指針im
unsigned char* fun() { unsigned char* p = malloc(N * sizeof(unsigned char)); return p; }
但若是你須要設置多個指針就不合適了。
另外一種辦法就是使用二級指針、三級指針。
int fun(unsigned char **p, unsigned char ***p1) { *p = (unsigned char *)malloc(N * sizeof(unsigned char)); if (NULL == *p) return -1; // 給二維指針p1分配 *p1 = fun_set_p1(); if (NULL == *p1) { free(*p); return -1; } return 0; } unsigned char* p; unsigned char** p1; fun(&p, &p1);
其實就是指向指針的指針。
函數內值傳遞,拷貝一份,其指向的內存的內容改變了,參數指向的內存的內容就跟着變了。