1. 程式人生 > >關於c中指標的一些理解****

關於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中會這樣):

void numplus(int a){
    a++;
}
void main(){
    int a=1;
    numplus(a);
    printf("%d",a);
}
像上面的一段程式碼,最後的執行結果是a=1,和預想中的結果a=2不同,這是因為在呼叫numplus()函式時,系統會重新在記憶體中建立一個名為a的整形變數,並不是將我們之前定義的a傳遞進去,numplus()函式執行,新建立的整形變數自增,numplus()執行結束,自動銷燬,此時新建立的變數a也跟著銷燬,從始至終,之前的變數a都沒有發生過改變,所以還是輸出1。想要通過函式實現變數自增需要用到指標(也有其他方法,就是將返回型別改成int,再用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函式方法中使用指標,只能傳遞指標

指向的記憶體地址,不能傳遞指標