盧政良 台大資訊系
指標
1 Pointer
https://www.youtube.com/watch?v=zaittayn5hw
https://hackmd.io/@sysprog/c-pointer
盧政良 台大資訊系
2
盧政良 台大資訊系
3
int
ptr x
類比
www.csie.ntu.edu.tw
arthurzllu@gmail.com
盧政良 台大資訊系
int* ptr = &x;
4
語法有三
讀作 ptr是 一個指標指到一個整數。
*ptr = 1;
&:取址運算子;回傳該變 數的記憶體位址。
address-of operator
* :取值運算子;存取 x值。
content-of operator
盧政良 台大資訊系
5
盧政良 台大資訊系
6
https://cdn2.ettoday.net/images/311/d311512.jpg
蟲洞
盧政良 台大資訊系
取x的值
取x的址 讓xptr紀錄x的址
取xptr的值 透過xptr取x的值!
取xptr的址!
透過xptr改x的值!
7
盧政良 台大資訊系
8
int add(int* a, int* b)
傳值 or 傳址, どっち?!
pass-by-address
int add(int a, int b)
比喻:送門市維修 vs. 到府服務?
pass-by-value
盧政良 台大資訊系
9
盧政良 台大資訊系
void swap(int* p1, int* p2)
10
不得不用指標的案例
盧政良 台大資訊系
11
丟地址,用什麼接?指標!
無法影響在 main裡的x和y
交換在 main裡的x和y
盧政良 台大資訊系
12
函式堆疊
5 3 x
y 步驟 1 / 3
int main() {
int x = 5, y = 3;
swap(&x, &y);
… (略) }
呼叫 swap
void swap(int* ptr1, int* ptr2) { int tmp = *ptr1;
*ptr1 = *ptr2;
*ptr2 = tmp;
}
盧政良 台大資訊系
13
函式堆疊
5 3 x
y 步驟 2 / 3
int main() {
int x = 5, y = 3;
swap(&x, &y);
… (略) }
void swap(int* ptr1, int* ptr2) { int tmp = *ptr1;
*ptr1 = *ptr2;
*ptr2 = tmp;
}
ptr1 ptr2 tmp 5
把手伸進x的箱子 把手伸進y的箱子
待って
盧政良 台大資訊系
14
步驟 3 / 3 函式堆疊
y 5
int main() {
int x = 5, y = 3;
swap(&x, &y);
… (略)
}
x 3
Void swap(int* ptr1, int* ptr2) { int tmp = *ptr1;
*ptr1 = *ptr2;
*ptr2 = tmp;
}
続ける
盧政良 台大資訊系
談談陣列與指標
15
盧政良 台大資訊系
A[i]
*(A + i) 等於
16
有目有看懂啊?!
┐(  ̄ヘ ̄)┌
語法上
頭腦體操
盧政良 台大資訊系
17
顯示 12 34 56
顯示 三筆資料的位址
所以我們可以透過指標操作陣列!
盧政良 台大資訊系
但,陣列變數 並非指標!
18
盧政良 台大資訊系
19
都是顯示 5
都是顯示 15
盧政良 台大資訊系
20
int A[5] int int int int int
0x00abc100
int* ptr
int B[5] int int int int int
0x00abc114 記憶體對齊問題
盧政良 台大資訊系
21
int A[5] int int int int int
0x00abc100
int* ptr
int B[5] int int int int int
0x00abc114
盧政良 台大資訊系
22
void sort(int A[], int size)
等於
void sort(int* A, int size)
陣列不會複製一份給函式,因為成本太高。
為什麼我們需要指標的第二個案例
盧政良 台大資訊系
23
練習
盧政良 台大資訊系
還是陣列與指標
24
(´Д `)
盧政良 台大資訊系
考慮此陣列工廠
25
印出來的東⻄是什麼!
盧政良 台大資訊系
26
任何動態配置的東⻄擺在這裡!!!
存放那些需要在函式使用到的 變數。這些變數都是暫時的,
即區域變數。
https://www.bogotobogo.com/cplusplus/images/assembly/
memory_diagram.png
盧政良 台大資訊系
new 和 delete
27
記憶體動態配置
創造 消滅
https://www.youtube.com/watch?v=SuBch2MZpZM
盧政良 台大資訊系
28 更新後的陣列工廠
把原來創造陣列的敘述換成這一行
盧政良 台大資訊系
29
忘了 delete 會怎樣嗎?
記憶體會無法釋放。
占著茅坑不拉屎。
memory leak
記憶體流失
盧政良 台大資訊系
30
int x;
int* ptr = &x;
int** dptr = &ptr;
dptr ptr x
dptr是一個指標的指標 ( point to int*); ptr是一個 指標 (point to int); x是一個整數 ( int)。
型態辨別方向:由右至左
雙重指標
(指標的指標)
盧政良 台大資訊系
誰會用到指標的指標?
31
盧政良 台大資訊系
32
二維陣列 (矩陣)
matrix
盧政良 台大資訊系
33
M M[0]
M[1]
M[0][0]
int int int int int
int
盧政良 台大資訊系
34
M M[0]
M[1]
M[0][0]
M[1][2]
int** int*
int int int int int
int* int
盧政良 台大資訊系
35
記得要刪兩層!
盧政良 台大資訊系
36
int** M = new int*[3];
M[0] = new int[4];
M[1] = new int[3];
M
M[0][0]
M[1][2]
M[1]
註:誰說陣列一定是方的!!!
nullptr 表⽰沒有指定位址
nullptr
盧政良 台大資訊系
37
int main(int argc, char** argv)
現在你可以知道這是什麼了吧!
我們認識的朋友
ヽ(*´∀`)八(´∀`*)ノ
盧政良 台大資訊系
* * *p
38
( (゚Д゚;))
盧政良 台大資訊系
函式指標
39
(( (゚Д゚Д゚Д゚)))
Functor
盧政良 台大資訊系
40
int (*f)(int, int);
例如
f是一個 函數指標,指到一個輸入為兩個整數且回傳一個整數的函數。
‣ 程式中所有的指令和資料皆需保存在記憶體裡,也因此 都對應到一個位址。
‣ 既然指標可以紀錄變數的位址,那當然也可以紀錄一個
函數的位址。
盧政良 台大資訊系
41
宣告一個函數指標 f
盧政良 台大資訊系
42
(void *):強制轉型成為指標。
可以觀察到函數的位址!
盧政良 台大資訊系
43
eArray, function, and pointer types are
collectively called derived declarator types.hh
C99 [6.2.5] Types
看起來毫不相干的東⻄居然是同一類!!!!!
更多關於指標:http://www.cplusplus.com/doc/tutorial/pointers/
盧政良 台大資訊系
自定義名稱
44
typedef
盧政良 台大資訊系
45
例如
typedef int (*Calculator)(int, int)
Calculator 是一個新的型態!
盧政良 台大資訊系
46
定義一個新的型態
是不是清爽很多?
盧政良 台大資訊系
常數
47
const
盧政良 台大資訊系
const int x = 1;
48
盧政良 台大資訊系
49
再回憶一次:由右至左
盧政良 台大資訊系
新的 for 迴圈
和
一個特別型態
50
C++限定
盧政良 台大資訊系
for (auto 元素變數 : 某資料結構 )
51
自動辨別型態
data structure
盧政良 台大資訊系
52
是不是清爽很多?
盧政良 台大資訊系
參考
53 Reference
C++限定
盧政良 台大資訊系
int& ref = x;
54
讀作 ref參考 整數x。
盧政良 台大資訊系
55
是不是清爽很多?
盧政良 台大資訊系
56
是不是清爽很多?
盧政良 台大資訊系
指標和參考的同異
‣ 參考是一個變數的別稱,實作上亦為 一個指標。
‣ 優點:不用像指標那樣一直加 * 。
‣ 限制:宣告參考時必須要指定目標,
且無法在之後進行更改。
57
不能移情別戀!(?)
盧政良 台大資訊系