從C語言的函數傳參談指針
Contact me:
Blog : https://cugtyt.github.io/blog/index
Email: cugtyt#qq.com, cugtyt#http://gmail.com
很多C語言的初學者在學習函數的時候會聽到,函數參數傳遞有兩種方式:傳值和傳地址。但是很容易給初學者造成誤區:函數參數傳遞真的有兩種方式。
其實,函數參數傳遞只有一種方式!只有一種方式!只有一種方式!
傳值和傳地址的說法不能說錯,但是考慮到真正理解,我們還是要細究一下。
void fun(int a);void funptr(int *a);
兩個函數的參數都是複製過去的,a是複製的,後面的指針a也是複製過去的,為什麼?
int value = 5;fun(value);funptr(&value);
fun將value複製給參數 int a ,funptr將value的地址複製給參數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容器