c語言的規則很簡單:「所有的引數都是傳值呼叫」。在這句話的基礎上,我們來分析值傳遞、指標傳遞、引用傳遞的區別。
一、值傳遞
值傳遞,這與c函式的性質有關。c函式的所有引數均以「傳值呼叫」方式進行傳遞,這意味著函式值將獲得引數值的乙份拷貝,函式可以放心修改這個拷貝值,而不必擔心會修改呼叫程式實際傳給他的引數。
我們先來看實現函式swap1:
void swap1(int a,int b)
main函式如下:
int a,b;
a = 5;
b = 6;
printf("實參a的值:%d ",a);
printf("實參b的值:%d ",b);
swap1(a,b);
printf("\n\n傳值交換後a,b的值:\n");
printf("實參a的值:%d \n",a);
printf("實參b的值:%d \n",b);
執行結果如下:
棧區(stack)— 程式執行時由編譯器自動分配,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。程式結束時由編譯器自動釋放。因此,引數a,b是存放在棧區的。在windows下,棧是向低位址擴充套件的資料結構,是一塊連續的記憶體的區域。因此,我們會看到a,b的位址是呈減少的趨勢。
因此,按照「值傳遞」的思想,形參是實參的拷貝,程式會開闢一塊新的棧區為形參。它們進行交換操作是在這塊新的棧區裡面,並不影響實參的那一塊記憶體。
執行完swap1函式,形參的記憶體中a,b的值發生了變化,但並不影響實參的的值。
在函式呼叫時,引數是從右到左讀的,所以b的位址比a的位址高
二、指標傳遞
我們來看實現函式swap2:
void swap2(int
*a,int
*b)main函式呼叫:
swap2(&a,&b);
printf("\n\n傳指標交換後a,b的值:\n");
printf("實參a的值:%d \n",a);
printf("實參b的值:%d \n",b);
執行結果:
因此我們可以看到,形參的值實際是實參的位址,因為c語言是值傳遞,main函式中傳入的是&a,&b即a,b的位址,所以形參中儲存的也是a和b的位址。
然後執行:
因此,他修改的是實參的內容。執行完後實參的內容應該是這樣的:
所以,這個時候a的值為6,b的值為5。
三、引用傳遞
我們來看實現函式swap3:
void swap3(int &a,int &b)
main函式呼叫:
swap3(a,b);
printf("\n\n傳引用交換後a,b的值:\n");
printf("實參a的值:%d \n",a);
printf("實參b的值:%d \n",b);
執行結果截圖:
lea eax,[ebp-8]是將b的偏移位址送入eax,
這個是swap2的彙編**,我們可以看到二者是一樣的。
66: swap2(&a,&b);
0040d979 lea edx,[ebp-8]
0040d97c push edx
0040d97d lea eax,[ebp-4]
0040d980 push eax
0040d981 call @ilt+10(swap2) (0040100f)
0040d986 add esp,8
所以,對於這裡的swap3和前面的swap2來講,堆疊中的函式引數存放的都是位址,在函式中操作的方式是一致的。但是,對swap3來說這個位址是主調函式通過將實參變數的偏移位址壓棧而傳遞進來的–這是引用傳遞;而對swap2來說,這個位址是主調函式通過將實參變數的值壓棧而傳遞進來的–這是值傳遞,只不過由於這個實參變數是指標變數所以其值是位址而已。
這裡的關鍵點在於,同樣是位址,乙個是引用傳遞中的變數位址,乙個是值傳遞中的指標變數的值。
四、總結
其實指標傳遞和值傳遞本質都是值傳遞,值傳遞是傳輸了要傳遞的變數的乙個副本。在c++中有引用傳遞,就是將要傳遞的變數的位址傳到了被呼叫函式中,如果在被呼叫函式中改變,那麼就會在呼叫函式中改變。
reference:
1.函式引數是如何傳遞的
2.《c和指標》第七章函式。
傳值 傳引用 傳指標
收藏 相關概念 c 三種傳遞引數方式 傳引數的值 稱值傳遞,簡稱傳值 傳引數的位址 稱位址傳遞,簡稱為傳址 和引用傳遞 稱為傳引用 相應的函式傳值呼叫,傳址呼叫和傳引用呼叫 形參 實參 函式定義時參數列中的引數稱為形式引數,簡稱形參 函式呼叫時參數列中的引數稱為實際引數,簡稱實參。實參和形參之間的資...
傳值 傳引用 傳指標
相關概念 c 三種傳遞引數方式 傳引數的值 稱值傳遞,簡稱傳值 傳引數的位址 稱位址傳遞,簡稱為傳址 和引用傳遞 稱為傳引用 相應的函式傳值呼叫,傳址呼叫和傳引用呼叫 形參 實參 函式定義時參數列中的引數稱為形式引數,簡稱形參 函式呼叫時參數列中的引數稱為實際引數,簡稱實參。實參和形參之間的資料傳遞...
傳值 傳引用 傳指標
剛學c時學的傳值和傳引用,傳指標忘得差不多了,再寫一遍,複習一下 1.傳值 2.傳引用 僅僅改變了畫圈的部分 傳引用的話,那麼改變的就是 本身了,自然就是不用替身,真身上啦 3.傳指標 改變的地方為畫圈的部分 這屬於傳指標的第一類,改變指標的直接引用,傳入的實參雖然也為副本,但是改變了副本的間接引用...