變數,其實就代表是一個有名稱的物件。
每個物件會佔據一段連續的記憶體空間,而在一般情況下,在同一次程式執行期間該物件的記憶體位址是固定的。
當我們寫下:
int a = 10;
//其實發生了三件事:
配置一段記憶體空間(例如 4 bytes)
這段空間有一個位址(例如 0x7ffee4a8)
我們用「a」這個名字來代表它
| 名稱 | 型態 | 位址 | 內容 |
|---|---|---|---|
| a | int | 0x7ffee4a8 | 10 |
其中,記憶體我們以位元組當單位,例如a佔據了4個位元組,而物件實際使用的記憶體位址指的是第一個位元組。
記憶體位址有以下特性
1.不同的物件通常會有不同的記憶體位址。
2.同一次執行裡面,同一個物件,記憶體位址不會改變
取址運算(&)
對變數名稱使用取址運算子(&),可以取得該物件的記憶體位址。
int a = 3;
cout << &a;
指標型態
指標型態是用來儲存記憶體位址的資料型態。
int *b;
指標型態變數
int* b = &a;
指標的間接運算
當我們有一個指標時
int a = 10;
int *b = &a;
//
a 是一個整數
b 是一個「儲存位址」的指標型態變數
b 裡面存的是 a 的位址
👉我們怎麼透過b去存取a的值?
*//取得指標所指向的那個位址中的內容
記憶體可能是這樣:
位址 內容
0x1000 10 ← a
0x2000 0x1000 ← b
當我們寫:
cout << *b;
發生的事情是:
1.讀取b裡面的值(0x1000)
2.跳到 0x1000
3.取出那個位置的內容(10)
4.印出 10
其中,初學容易混淆的地方
//*有兩種意思
int *b; 宣告指標型態
*b 間接運算,取值
總結
取址運算子(&):取得物件的記憶體位址
指標型態(T*):儲存記憶體位址的資料型態
間接運算子(*):取得指定記憶體位址上的物件
int a = 3;
int* b = &a;
cout << b << endl;
//*&a的結果是a
//*&b等價於b
//*b = *&a = a = 3
指標物件的賦值運算
一般我們在做賦值運算時(如下),a與b是兩個不同的變數,也是不同的物件。
a存的是3,而b存的是a的複製品,因此,在對b直接賦值的情況下,並不會改到a。
int a = 3;
int b = a;
b = 5;
cout << a << endl;//a = 3
cout << b << endl;//b = 5
而指標物件的間接賦值(如下)則不同,a儲存數值3,b儲存的是a的記憶體位址,而*b代表「b所指向位址中的內容」,也就是a。
int a = 3;
int* b = &a;
*b = 5;//= *&a,*&a的結果等價於a,因此a = 5
cout << a << endl;//a = 5
因此,有了指標之後,存取物件除了可以透過變數名稱,也可以透過儲存該物件位址的指標來間接存取。
如果你也是非本科背景,或正準備開始學習程式,希望這篇筆記能對你有所幫助。
這裡會持續記錄我在轉職過程中對程式、軟體工程與實務學習的理解,歡迎一起交流,也歡迎指教。
如果這篇內容對你有幫助,歡迎收藏或分享給正在學習程式的朋友。