函數傳參有三種傳參方式:傳值、傳址、傳引用。
我們可能聽過C語言中的傳值和傳指針,在其他語言中,也有傳引用一說,那么他們到底有什么區別呢?如果你還不能準確地分辨,就該好好了解一下了。
傳值
我們在初學C語言的時候就被老師教過,下面的方式是無法交換a和b的值的:
#include
運行結果如下:
beforeswap:a=10,b=20 internalswapa=20,b=10 afterswap:a=10,b=20
可以看到,a和b的值最終并沒有被交換。開始時a,b的值為10,20,而最終還是同樣的值。
為什么呢?因為函數參數在傳遞的時候,都是傳原數據的副本,也就是說,swap內部使用的a和b只是最初始a和b的一個副本而已,所以無論在swap函數內部對a和b做任何改變,都不會影響初始的a和b的值。
正因如此,我們常常被告知,不要把直接把結構體直接作為參數,這樣效率會很低。由于結構體本身占用字節數較大,如果直接作為參數,那么將會產生一個較大的”副本“,如此一來,效率也就很低了。
我們再結合下面的圖來理解:
值傳遞
首先圖中方框中的上部分a和b代表了main函數中的a和b,即原始數據,而方框中的下部分a和b代表了函數的參數a和b,即原始數據的“副本”。(后面的圖都是如此,上部分代表原始值,下部分代表函數參數值)。
調用swap函數前后的情形如下:
調用swap前后
由于在swap中永遠只是對a和b的副本進行操作,因此完全不影響原始的a和b的值。最終也不可能達到交換a和b的值的目的。
傳指針
那么為解決上面的問題,我們知道,需要傳指針。其代碼如下:
#include
運行結果:
beforeswap:a=10,b=20 swapa=20,b=10 afterswap:a=20,b=10
可以看到在這種情況下,a,b的值才是真正交換了。
為什么又有傳值,又有傳指針
看到這里,不知道你是否會疑惑,為什么給函數傳遞參數的時候,一會是傳值,一會是傳指針呢?為什么傳指針就能改變參數的值呢?實際上,C語言里,參數傳遞都是值傳遞!也就是說,你認為的傳指針也是傳值,只不過它的值是指針類型罷了。
我們再通過圖來理解前面為什么傳指針就可以交換a,b的值:
從圖中可以看出,雖然傳遞給函數的是指向a和b的指針的副本,但是它的副本同樣也是指向a和b,因此雖然不能改變指針的指向,但是能改變參數a和b指向的內容,即改變原始a和b的值。
再看傳指針
如果是為指針p申請一段內存,下面的代碼能達到目的嗎?
#include
通過前面的內容分析,肯定是達不到預期效果的。
運行結果:
addressofpis(nil)
這是為什么呢?我們還是利用前面所知來分析,由于傳遞給getMemory函數的參數都是一個副本,因此函數內的p也是外部p的一個副本,因此即便在函數內部,將p指向了一塊新申請的內存,仍然不會改變外面p的值,即p還是指向NULL。
getMemory
如何修改呢?我們需要傳入p的地址,即指向int類型指針的指針。
#include
運行結果如下:
addressofpis0x144f010
從運行結果可以看到,p的值被改變了,而不再是初始的NULL。
可配合下面的圖進行理解:
getMemory
總結
本文總結如下:
函數的參數都是原數據的“副本”,因此在函數內無法改變原數據
函數中參數都是傳值,傳指針本質上也是傳值
如果想要改變入參內容,則需要傳該入參的地址(指針和引用都是類似的作用),通過解引用修改其指向的內容
以上結論不限于C語言
-
C語言
+關注
關注
180文章
7604瀏覽量
136692 -
函數
+關注
關注
3文章
4327瀏覽量
62571 -
指針
+關注
關注
1文章
480瀏覽量
70551
原文標題:C語言函數參數的傳值和傳指針有什么區別?
文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論