*p兩種使用狀況:數組
1.定義指針變量,如char *p;這裏p是一個變量,單單在這一點上與int a 無差異;但p這個變量特殊在其中只能存地址。函數
引伸:對於char **p,p中存一個地址add1,add1對應存儲區存放add2,而add2地址對應存儲區才存放有真正的data;以下圖1所示:spa
2.*p,用來取p中所存地址對應存儲區的數據,如上圖2所示。指針
例如:主函數main中有char *p,p=。。。令p中存放某一內存首地址。這時調用子函數,若想在子函數fun中修改p指向的內存,必須:code
(1)要獲得p的地址即fun(&p),而後用*p=。。。才能需改p指向的內存,具體以下:blog
void func(char **p2) { char *p1 ; //p1 = (char *)malloc(sizeof(char) * 8); p1 = "hello"; *p2 = p1; } int main(){ char *p = NULL; func(&p); printf("p=%s\n",p);//打印p指向內存所存字符串。 getchar(); return 0; } 輸出:hello
(2)若不想傳地址,就須要子函數帶返回值,程序以下:內存
char * func(void) {
char *p1 ;
p1 = "hello";
return p1; } int main(){ char *p = NULL; p=func(); printf("p=%s\n",p);//打印p指向內存所存字符串。 getchar(); return 0; }
輸出:hello
引伸:下面給出一些案例字符串
一個典型錯誤:get
看你能不能找出來:class
1 void t(char **p2){ 2 char *p1 ; 3 p1 = (char *)malloc(1); 4 *p2 = p1; 5 } 6 int main(){ 7 char **p ; 8 9 t(p); 10 return 0; 11 } 爲何一運行就提示p沒有初始化。
改進:下面爲對**p正確應用的例子:
void t(char **p2) { char *p1 ; //p1 = (char *)malloc(1); p1 = "hello"; *p2 = p1;//*p原本指向arr[],如今指向"hello"所在內存區域首地址,因此堆arr[]沒影響。 } int main(){ char **p; p = (char **)malloc(sizeof(char) * 8); char arr[] = "zhang"; *p = arr;//*p中存放arr地址,區別於p = (char **)arr直接p中存放arr地址
printf("a[0]=%c\n",arr[0]);
t(p);
printf("*p=%s,p=%d\n",*p,p);
printf("a[0]=%c\n",arr[0]);
return 0;
}
輸出:
a[0]=z
*p=hello,p=13531344//不一樣人結果不同。
a[0]=z
這種方式本來的arr[]數據還在,只是*p不指向了,*p指向了「hello」所在內存的地址。
再看一種:注意與上面程序對比,你就能明白**p到底這麼用。
void t(char **p2) { char *p1 ; p1 = "hello"; *p2 = p1;//p存放arr地址,*p 對應arr[0]的值,所以這句會破壞原理的arr數組。 } int main(){ char **p; //p = (char **)malloc(sizeof(char) * 8); char arr[] = "zhang"; p = (char **)arr;//*p = arr思考註釋中的這種方式的差異?//p存放arr地址 printf("a[0]=%c\n",arr[0]); t(p); printf("p=%s,p=%x\n",*p,p); printf("a[0]=%c\n",arr[0]); return 0; }
輸出: a[0]=z p=hello,p=75fe70 a[0]=?思考:爲何結果和上面程序不同。其實註釋裏已經給出了答案,哈哈。