一級指標還是二級指標作函式引數(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