1. 程式人生 > >一級指標還是二級指標作函式引數(2)

一級指標還是二級指標作函式引數(2)

程式1:

void  main()  

{  
     char  *p=NULL;  
     myMalloc(p);    //這裡的p實際還是NULL,p的值沒有改變,為什麼?  
     if(p)  free(p);  

void  myMalloc(char  *s)  //我想在函式中分配記憶體,再返回  
{  
     s=(char  *)  malloc(100);  
}  

myMalloc(p)的執行過程:  
分配一個臨時變數char  *s,s的值等於p,也就是NULL,但是s佔用的是與p不同的記憶體空間。此後函式的執行與p一點關係都沒有了!只是用p的值來初始化s。  
然後s=(char  *)  malloc(100),把s的值賦成malloc的地址,對p的值沒有任何影響。p的值還是NULL。  

注意指標變數只是一個特殊的變數,實際上它存的是整數值,但是它是記憶體中的某個地址。通過它可以訪問這個地址。  

程式2:

void  myMalloc(char  **s)  

{  
     *s=(char  *)  malloc(100);  
}  
void  main()  
{  
     char  *p=NULL;  
     myMalloc(&p);    //這裡的p可以得到正確的值了  
     if(p)  free(p);  
}  
程式2是正確的,為什麼呢?看一個執行過程就知道了:  
myMalloc(&p);將p的地址傳入函式,假設儲存p變數的地址是0x5555,則0x5555這個地址存的是指標變數p的值,也就是Ox5555指向p。  

呼叫的時候同樣分配一個臨時變數char **s,此時s  的值是&p的值也就是0x5555,但是s所佔的空間是另外的空間,只不過它所指向的值是一個地址:Ox5555。  
*s=(char *)malloc(100);這一句話的意思是將s所指向的值,也就是0x5555這個位置上的變數的值賦為(char *)malloc(100)(並不是改變p的地址值0x5555,而是指標變數p本身的值,而0x5555這個位置上存的是恰好是指標變數p,這樣p的值就變成了(char *)malloc(100)的值。即p的值是新分配的這塊記憶體的起始地址。  

這個問題理解起來有點繞,關鍵是理解變數作函式形參呼叫的時候都是要分配一個副本,不管是傳值還是傳址。傳入後就和形參沒有關係了,它不會改變形參的值。myMalloc(p)不會改變p的值,p的值當然是 NULL,它只能改變p所指向的記憶體地址的值。但是myMalloc(&p)為什麼就可以了,它不會改變(&p)的值也不可能改變,但是它可以改變(&p)所指向記憶體地址的值,即p的值。  


程式3:  
#include  
 
void  fun(int  *p)  
{  
       int  b=100;  
       p=&b;  
}  
 
main()  
{  
       int  a=10;  
       int  *q;  
       q=&a;  
       printf("%d\n",*q);  
       fun(q);////道理同第一個程式  
       printf("%d\n",*q);  
       return  0;  
}  
結果為  
10  
10  

程式4:  

void  fun(int  *p)  
{  
       *p=100;//引數p和實參q所指的記憶體單元是相同的.所以改變了引數P的記憶體單元內容,就改變了實參  
                     //的記憶體單元內容  
}  
main()  
{  
       int  a=10;  
       int  *q;  
       q=&a;  
       printf("%d\n",*q);  
       fun(q);  
       printf("%d\n",*q);  
       return  0;  
}  
結果為  
10  
100