天天看點

值傳遞與位址傳遞的了解

相信很多c語言的初學者在剛剛面對指針時的窘迫,确實指針是c語言的精華,從開始時強記指針就是位址,到現在的,我認為如果計算機中的資料看作均看作對象,指針就用來指引着這些對象,通過指針可以用來對這些對象進行修改。

值傳遞和位址傳遞是一個非常容易犯錯的地方,給大家帶來一個

#include<stdio.h>

int fun(int a,int *b){

a=100;

*b=200;

printf(“形參a的位址為%p,形參b的位址為%p\n”,&a,b);

}

int main(){

int a=10,b=20;

printf(“a=%d\t 實參a的位址為:%p \tb=%d 實參b的位址為%p\n”,a,&a,b,&b);

fun(a,&b);

printf(“a=%d,b=%d”,a,b);

}

值傳遞與位址傳遞的了解

通過實驗結果可以看到,局部變量a傳遞的是值,b傳遞的是位址,對于值傳遞被調函數對形參的操作并不能改變主調函數中實參的值,位址傳遞可以改變,我們從記憶體的角度看一個,實際上值傳遞被調函數相當于重新定義了一個變量存儲實參a的值他們的是兩個完全不同變量,位址不一樣在記憶體中的位置也不一樣,隻是把主函數中a的值拷貝了,試想他們是兩個完全不同的東西如何能夠通過形參a改變實參a的值,被調函數結束後形參a被釋放,也與實參a無關了,實參a住的房子,會在主函數執行完釋放

而位址傳遞時把變量b的位址傳遞到形參裡去了,他們的位址時一樣的住在同一間房子裡,我們知道記憶體是由存儲單元構成,*b相當于打開記憶體單元,向裡面放入200這個值,在主函數結束之前200都将在這個房子裡面,是以主函數中b的值已近被覆寫

#include<stdio.h>

int c[5]={5,6,7,8,9};

int print(int a[],int n,int a1[]){

printf(“a=”);

for(int i=0;i<n;i++){

printf("%d\t",a[i]);

}

printf("\n");

printf(“a1=”);

for(int i=0;i<n;i++){

printf("%d\t",a1[i]);

}

printf("\n\n\n");

}

int fun(int **a,int n,int a1[]){

*a=c;

a1=c;

}

int main(){

int b[5]={1,2,3,4,5};

int *a,*a1;

a=b;

a1=b;

print(a,5,a1);

printf(“a=%p\ta1=%p\n”,a,a1);

fun(&a,5,a1);

printf(“a=%p\ta1=%p\n”,a,a1);

print(a,5,a1);

}

上面傳遞的一級指針,這裡傳遞的是二級指針,二級指針裡儲存的是一級指針的位址,一級指針指向數組b,然後傳遞一級指針的位址,在被調函數中是二級指針a指向數組c,主函數中a的指向也就變了,如果不是,而a1傳遞的也是位址,隻是一級指針的位址,一級指針的位址隻能改變數組b中的值,而二級指針改變的是a的指向a的位址也改變了,是以你要改變變量的(值)就得傳遞它的位址,

值傳遞與位址傳遞的了解

注意在被調函數中用一段代碼是我注釋了的,如果int c[5]={1,2,3,4,5}定義成立局部變量就是有問題的,當函數傳回時,c的記憶體空間會從棧中釋放,這時a就稱為野指針了,編譯器不會報錯,但這是不允許的,不要傳回局部變量的位址,也是很多人一不小心就會範的錯誤,而且如果經驗不足不易看出,傳遞和傳遞值都隻是相對而言的,取決的時你想改變的是什麼,在第二例子裡,b裡的值可以被形參a1所改變,但是實參a1的指向确實改變不了,願因是傳遞的是一級位址,就隻能改邊低一級的變量,二級指針可以改變一級指針的指向(也就是值),同理三級指針可以改變二級指針的值,一級指針可以改邊變量的值。

繼續閱讀