首先看代碼:
void fun(int * p) ;
int * pBuf = NULL; //****************(1)
fun(pBuf); //****************(2)
void fun(int * p) //****************(3)
{
p = (int*)malloc(10*sizeof(int)); //****************(4)
}
下面分析一下在每行代碼中都發(fā)生了什么:
在 (1) 中,聲明pBuf為int *類型虫腋,指向int類型身冬。此時(shí),pBuf 是指針岔乔,其是有值的,即有內(nèi)存地址(假如是:0x00007fff5fbff620)滚躯,但其指向的內(nèi)存卻為空NULL雏门。
在 (2) (3)中,pBuf 作為實(shí)參傳入函數(shù) fun(int * p) 中(p為形參掸掏,此時(shí)p為int * 類型茁影,指向int類型)。p =pBuf丧凤,亦為0x00007fff5fbff620募闲,具有相同地址。
在 (4) 中愿待,malloc申請(qǐng)一塊內(nèi)存浩螺,并返回指向此內(nèi)存的地址,并給了p仍侥,此時(shí) p 指向了malloc申請(qǐng)的內(nèi)存要出,p有了新的地址,與pBuf不再相等农渊,不再為0x00007fff5fbff620患蹂。而此時(shí)pBuf卻沒有改變,依然是0x00007fff5fbff620砸紊。
所有這種方法并不會(huì)為pBuf改變什么传于,仍然指向NULL。但是pBuf是有內(nèi)存地址的(初始化的時(shí)候就有),卻指向NULL醉顽,即并沒有開辟內(nèi)存沼溜,所有不能對(duì)pBuf進(jìn)行賦值,因?yàn)槠錄]有內(nèi)存存儲(chǔ)值徽鼎。
再看另一種方式:
void fun(int ** p) ;
int * pBuf = NULL; //****************(1)
fun(&pBuf); //****************(2)
void fun(int ** p) //****************(3)
{
*p = (int*)malloc(10*sizeof(int)); //****************(4)
}
同樣的分析一下上面每行代碼中都發(fā)生了什么:
在 (1) 中盛末,與第一段代碼沒什么區(qū)別。假如:pBuf = 0x00007fff5fbff620否淤,&pBuf=0x00007fffaaae0f70悄但,* pBuf = NULL。
在 (2) (3)中石抡,&pBuf作為實(shí)參傳入函數(shù)fun(int ** p)中(p為形參檐嚣,此時(shí)p為int** 類型,即為指針的指針),p=&pBuf(0x00007fffaaae0f70)嚎京。指向 int* 類型嗡贺,即指向了指針,這個(gè)指針其實(shí)就是pBuf鞍帝,即 p 指向了 pBuf 诫睬,所以 * p其實(shí)就是 pBuf (0x00007fff5fbff620)。此時(shí)別忘記帕涌,0x00007fff5fbff620 是指向NULL的摄凡。
在 (4) 中,malloc申請(qǐng)一塊內(nèi)存蚓曼,并返回指向此內(nèi)存的地址亲澡,并給了 *p,此時(shí) *p 指向了malloc申請(qǐng)的內(nèi)存纫版。此時(shí) p依然沒有改變床绪,與&pBuf相等(0x00007fffaaae0f70),但是p指向的地址卻改變了其弊,指向了一塊新的內(nèi)存癞己。所以0x00007fffaaae0f70指向的一個(gè)新的內(nèi)存地址,而這個(gè)內(nèi)存地址也指向的一塊內(nèi)存梭伐,不再是NULL末秃。
總結(jié):
第一段代碼,傳入了指向空內(nèi)存的地址籽御,最后改變了形參p的地址练慕,與傳入的pBuf不再相等,所有沒有對(duì)pBuf進(jìn)行改變什么技掏。
第二段代碼铃将,傳入了指向指針pBuf的指針,最后改變的是p指向的地址哑梳,而p依然是指向指針pBuf的指針劲阎。最后其實(shí)是改變了傳入的指針的指向,即改變了&pBuf的指向鸠真,讓其指向了新的地址悯仙。