子函數內malloc分配內存,論如何改變指針參數所指內存,二級指針、三級指針的應用


工作中優化一段代碼,代碼中有一大段分配堆內存的內容,我覺得這段代碼太長了,更適合放在子函數里面。

我把指針作為參數,然后在子函數中malloc分配內存,結果出現了問題,函數結束后,以參數傳進來的指針並沒有指向分配的內存。

比如說:

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並沒有發生變化。

指針作為參數不是傳的是地址嗎?怎么沒變化呢?

 

其實這樣想是一種誤區,其實指針作為參數也是值傳遞,在函數中將參數復制一份而已。指向的是同一塊內存地址。假設參數傳的是int *p,函數內copy的j是int *p_1。在函數中操作*p_1,例如*p_1 = 1, 則p_1所指向的內容就變成了1.,由於他們是指向同一塊地址,所以即使他們不是同一個指針*p所指向的內存也會被改變。

 

但如果讓p_1指向其他的內存地址,則由於是值傳遞,p並不會因此而改變。

 

其實反匯編可以看出,參數的傳遞其實就是將變量放入新開辟的函數棧空間,也就是我說的“copy一份”,函數中再對棧空間里的內容操作,這就是值傳遞的本質。

 

所以這種情況該怎么辦呢?

一種情況是函數 返回 指向新申請內存的指針

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);

其實就是指向指針的指針。

函數內值傳遞,拷貝一份,其指向的內存的內容改變了,參數指向的內存的內容就跟着變了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM