從C語言的函數傳參談指針

Contact me:

Blog : cugtyt.github.io/blog/i

Email: cugtyt#qq.com, cugtyt#gmail.com


很多C語言的初學者在學習函數的時候會聽到,函數參數傳遞有兩種方式:傳值和傳地址。但是很容易給初學者造成誤區:函數參數傳遞真的有兩種方式。

其實,函數參數傳遞只有一種方式!只有一種方式!只有一種方式!

傳值和傳地址的說法不能說錯,但是考慮到真正理解,我們還是要細究一下。

void fun(int a);void funptr(int *a);

兩個函數的參數都是複製過去的,a是複製的,後面的指針a也是複製過去的,為什麼?

int value = 5;fun(value);funptr(&value);

funvalue複製給參數 int afunptrvalue的地址複製給參數int *a,C語言的參數傳遞非常純粹和簡單,就是複製複製複製!地址也是複製過去的。

談到這裡我來談談指針,指針也是個存粹的東西,不過他的內容是個內存的地址而已,僅此而已,我們使用內容需要加*來訪問,僅此而已,地址和實際內容並沒有物理上的聯繫,只是有邏輯聯繫而已。

如果你認為第一個內存單元的內容是個數,那它就是500,如果你認為第一個內存單元的內容是個地址,那麼*訪問就是xxx,因此我們可以寫這樣的東西:

int a = 0;int b = (int)&a;printf("%d", *(int *)b);

當然,要指針和int的長度一致才有效。

我們可以把a的地址存入一個int,而不是int*,取內容的時候只需要轉換回int*,再*就可以取出a的內容了。

不僅僅是C,Java也是,所謂的引用就是指針了,因此,如果寫Java的時候傳入空指針,Java就會拋出空指針異常,是不是很熟悉的異常。值得注意的是,如果你在函數內部對指針參數直接複製,例如funptr函數裡面直接寫:a = xxx,那麼不會對原來的內容做修改,因為你的a是複製的。

如圖,修改函數裡面的指針為其他比如400,並不會對第500內存單元的內容有影響。

C++的引用可能就是另一個故事了,引用沒有複製,邏輯上相當於直接對原來的東西做處理,而不是複製一個新的指針,再通過指針處理。

為什麼我們需要指針?

考慮通過函數交換兩個數字的經典問題,正因為參數是複製的,因此我們改變參數對原來的值沒有影響,那怎麼辦,通過地址操作,記住兩個數字的地址,我們就直接對原來的值做了修改。還有,考慮一個占很大空間的變數,複製它比較消耗時間,怎麼辦,通過地址,只要記住它的地址,我們只需要複製地址,就可以在需要的時候對它做處理,而不用每次複製這個變數。

說白了,指針就是一個存地址的東西,只不過我們把它寫的比較特別,要加*,這樣大家都知道這個變數是存地址的,而不是個普通的變數,指針就是這樣。


推薦閱讀:

簡化深度學習實踐流程:新鮮出爐的TensorFlow項目模板來了
上線一星期後,來聊聊小程序的「預想之中」和「意料之外」?
有什麼你覺的很好的 idea,卻一直沒時間來實現?
GacUI 動畫系統 (3:漸變動畫)
C++中關於跨平台中子線程式控制制的一些心得(2):用於線程的同步的Async容器

TAG:C編程語言 | 編程 | 指針 |