關於c中指標的一些理解****
接觸到一個指標,先不要想它指向哪裡,而是把它當成一個變數,這個變數裡面存放的值指向哪裡。
&取值符,一個變數前邊加上它,就代表取該變數的記憶體地址。
*解指標符,例如:int a=10, *(&a)取的就是該變數的記憶體地址中存放的內容。
例:int a=10; int *p_a=&a; int **p_p_a=&p_a;
定義一個整形變數a的值是10,定義一個指標p_a指向a的記憶體地址&a,定義一個指向指標的指標p_p_a指向p_a的記憶體地址&p_a(&p_a的記憶體地址中的值就是a的記憶體地址)。所以*p_a=10,**p_p_a=10;
定義一個整形變數並給他賦值,如:int a=10; 這時會在記憶體中隨意找到一個空間,它儲存的值是10。記憶體會有類似一系列的小空間,每個空間都有對應的地址,地址使用16進位制的數字來表示(0x01)。如圖(這裡0x沒有寫):
像這樣,定義的一個指標p就指向a所在的記憶體地址。這時,如果想通過指標來改變a的值,需要這樣寫,下面的 改變的是p指向的記憶體地址,而不是記憶體地址中的值。
舉個例子(只是在c中會這樣):
像上面的一段程式碼,最後的執行結果是a=1,和預想中的結果a=2不同,這是因為在呼叫numplus()函式時,系統會重新在記憶體中建立一個名為a的整形變數,並不是將我們之前定義的a傳遞進去,numplus()函式執行,新建立的整形變數自增,numplus()執行結束,自動銷燬,此時新建立的變數a也跟著銷燬,從始至終,之前的變數a都沒有發生過改變,所以還是輸出1。想要通過函式實現變數自增需要用到指標(也有其他方法,就是將返回型別改成int,再用a來接收),如下程式碼:void numplus(int a){ a++; } void main(){ int a=1; numplus(a); printf("%d",a); }
void numplus(int *p){ (*p)++; } void main(){ int a=1; numplus(&a); printf("%d",a); }
像這樣,a就會自增,這樣呼叫numplus()函式時,會將a的記憶體地址也就是&a複製給numplus(),就會重新生成一個指標*p,指標*p指向&a,函式執行(*p)++,就是p指標指向的記憶體地址的值進行自增,函式執行結束後,新生成的*p指標就會銷燬掉,可是a中的值也就是&a這個記憶體地址所儲存的值已經發生改變,最後就會輸出預期結果2.
再舉一個例子:
定義一個數組,一個指標指向陣列的第一個資料元素,定義一個方法使指標向後移一位,指向第二個元素。
void remove_p(int arr[],int *p){
p=&arr[1];
}
void main(){
int arr[5]={1,2,3,4,5};
int *p=&arr[0];
printf("%d\n",*p);
remove_p(arr,p);
printf("%d\n",*p);
}
發現結果輸出的仍然是1,這是因為在呼叫函式時傳遞的是指標p,remove_p()函式會重新生成一個指標p,remove_p()函式執行改變的是新生成的指標p所指向的地址,remove_p()函式執行完畢,新生成的指標p就會被銷燬,從始至終想要改變的指標p都沒有發生任何改變,輸出結果也就是1了。想要通過函式來改變的p需要像這樣寫(也可以改變返回值將函式生成的指標賦給p):
void remove_p(int arr[],int **p){
*p=&arr[1];
}
void main(){
int arr[5]={1,2,3,4,5};
int *p=&arr[0];
printf("%d\n",*p);
remove_p(arr,&p);
printf("%d\n",*p);
}
這樣寫,在呼叫remove_p()函式時,將p指標的記憶體地址傳遞給remove_p()函式(不是p指標,傳遞p指標會報錯,**p是接收地址),這樣remove_p()函式就會生成一個新指標,新指標指向p的記憶體地址,也就是說新指標的值就是p的記憶體地址,remove_p()函式執行,改變p的記憶體地址後,新指標銷燬,但是p的記憶體地址已經被改變。
總結:
指標在函式這裡的使用:
在函式的形參為int
*p時,想要呼叫函式,不需要定義指標(也可以定義),只需將變數的記憶體地址&a傳遞過去即可。
但是當一個指標指向的是一個數組中的某元素,想要呼叫函式改變指標時,函式形參為int **p時,這時引數只能接收
定義的指標所指向的記憶體地址也就是&p.而不能接收指標。也就是說,想在void函式方法中使用指標,只能傳遞指標
指向的記憶體地址,不能傳遞指標