我理解的指標與引用

2021-08-20 12:34:47 字數 2592 閱讀 6909

最近在學習golang的過程中,發現乙個有意思的事情,有的文章說函式呼叫傳參時slice是引用傳遞,有的說是值傳遞。為什麼同乙個東西大家會不同認識?為了搞清楚其本質,我進行了以下內容的研究:

變數的變數名、變數值、變數位址在記憶體中是怎麼樣的?

指標的定義是什麼?引用的定義是什麼?二者有什麼關係?

函式傳參中值傳遞、指標傳遞與引用傳遞到底有什麼不一樣?

go中slice在傳入函式時到底是不是引用傳遞?如果不是,在函式內為什麼能修改其值?

上學的時候,老師講變數是存在記憶體中的,記憶體就像一排排抽屜組成的,每個抽屜上面有個編號,我們定義乙個變數,就是把想放的東西放到這個對應編號的抽屜裡。比如: int a = 10,用圖來表示下:

這裡:變數的名字叫a,變數的值是:10,變數的位址是:0x 00000001

那麼問題來了,變數的值我們知道是放在了抽屜裡(記憶體中),每個抽屜有編號(位址),但是變數的名字a存放在**呢?或者說它會存在於記憶體中嗎?

大家想乙個問題,如果變數的名字要存放在記憶體中,那麼肯定分配乙個空間給他,儲存它的空間有個位址,這個位址是不是又得有個地方存起來程式才能找到?如果真是這樣設計,那麼**根本沒發寫、無法執行了。

其實變數名僅僅是寫給程式設計師看的,讓我們寫**的時候知道這個變數有什麼用,能夠通過名字呼叫變數的值。因為如果直接給你乙個位址 0x 23004123,你知道這是要幹嘛嗎?**經過編譯後,最終都會轉換成機器碼,我們定義的變數名就都不存在了,存在的只有位址跟值。

有了上面的理解,再來乙個特殊的變數:指標變數。什麼叫指標變數呢?其實就是這個變數裡邊存放的是乙個變數的位址,通過這個位址,機器可以找到對應變數的值,例如:int * pa = &a,就表示變數pa抽屜裡放的是a的位址,它的型別是:int*,繼續看圖:

繼續談引用,引用與指標我們經常傻傻分不清,因為它們的行為確實非常詭異,看起來效果非常相似,看**:

由於引用的概念是在 c++ 中引入的,因此下面的**使用c++,僅僅是一些列印而已,放心看下去

int main()
通過上面的**我們發現,指標與引用都能達到乙個效果:都有能力修改a的值,指標前面講過了,因為它儲存了a的位址,通過解引用操作後,實際上就是開啟了a的抽屜,因此可以進行修改。那麼引用又是怎麼辦到的?這裡注意乙個細節:*pa = 20; c = 30;a = 40。我們看到操作c的時候與操作a是一樣的方式:直接使用變數名,但是pa要想改變a的值,必須進行 *pa 操作(解引用),如果直接 pa=20,這僅僅是改變的pa的值,讓他指向了另外乙個位址。

為什麼引用與變數是一樣的操作方式?先來看一下引用的定義:

引用就是某一變數的乙個別名,對引用的操作與對變數直接操作完全一樣。

那麼別名是什麼意思呢?繼續看圖,一看就懂

通過上面的分析不知道你理解了幾分?或者你是不是對指標與引用還是半信半疑?沒關係,寫點**證明一下即可,我們要證明的是:

- 引用是變數的別名,那麼它的位址應該與變數一致;

- 指標儲存的是變數的位址,那麼它的值是變數的位址,它自身的位址與變數不同。

int main()
獲得輸出:

10 // 變數a的值

0x7ffee3c7a768 // 變數a的位址

~~~~~~~~~~~~~~

0x7ffee3c7a768 // 指標的值,是變數a的位址

0x7ffee3c7a760 // 指標變數自己的位址

~~~~~~~~~~~~~~

10 // 變數a的值

0x7ffee3c7a768 // 引用變數c的位址,與變數a的位址完全一樣

在上面如果指標想要列印變數a的值,需要解引用操作:printf(「%d\n」, *b);

變數名實際上只是給程式設計師看的,編譯後的**中並不存在變數名;

指標變數就是乙個變數儲存了另外乙個變數的位址,系統也會為他分配記憶體空間來儲存這個位址;

引用實際是變數的別名,他跟變數有相同的位址。

下次預告:

1. 函式傳參中值傳遞、指標傳遞與引用傳遞到底有什麼不一樣?

2. 為什麼說slice是引用型別?

3. go中slice在傳入函式時到底是不是引用傳遞?如果不是,在函式內為什麼能修改其值?

引用與指標的理解

指標變數用於儲存資料的位址,使用方法如 int i 0 int p p i 此時,p 的值為i 的位址,p為位址所儲存的數值也就是 i的值,i的值為位址所存放的值也就是 p的值,i的值為 i p i p i 引用為c 才有的功能,引用變數不占用記憶體,可理解為函式的別名,使用方法如 int i 0 ...

我理解的指標與陣列 02

前言 c 陣列名參與 運算後就會退化為指向該陣列元素型別的指標。文章末位我已經點明了其中c結論是有問題的,其實前邊兩條我也不敢很自信的說他們是完全正確的。但是我理解的就是這樣,我也反覆推敲過,感覺暫時已經到了我能力的極限不可能再做出更好的優化和這總結了。總之,現階段這三條結論我覺得已經表述清楚了我的...

C 指標的引用理解

指標可以作為引數傳遞直接修改所指的變數的值,如下 void change int p int main 指標傳遞實際上也是值傳遞,傳遞的值便是指標的位址,執行 p 20後,雖然傳遞的是乙個位址的副本,但是副本的值就是變數的位址,執行後,所指向的位址的值變成了20,達到了修改變數值的目的。所以,當需要...