###### tags: `sprout`
# pointer
clang 2021 廖凰汝
---

----

----
```cpp=
int a = 10;
```
當宣告一個變數,會將他放在電腦的某一個位置

----
```cpp=
int a = 10;
```
當宣告一個變數,會將他放在電腦的某一個位置

----
怎麼知道變數在電腦的位址是什麼?

----
```cpp=
#include <iostream>
int main() {
int a = 10;
std::cout << "變數a的位址在" << &a << std::endl;
}
```
----
可是我想要把變數a的地址存起來!
```cpp=
int a_address = &a; // 可以用int存嗎?
double a_address = &a; // 還是double ?
// ......
// 目前知道的型態都不符合
```
----
## 指標 pointer
```cpp=
int *ptr = &a;
int* ptr = &a;
```
----
## 指標 pointer
就是一個變數,用來存放**變數的位址**
----
注意!如果我們想宣告兩個指標變數
以下有什麼問題?
```cpp=
int* ptr1, ptr2;
// same as int* ptr1; int ptr2;
```
```cpp=
int *ptr1, *ptr2;
```
----
回到房子的例子。
如果我們知道房子的位址,想知道裡面的值?
我們需要一把鑰匙。
----

```cpp=
int a = 10;
int *ptr = &a; // ptr 存變數a的位址
cout << "a的內容是什麼?" << *ptr;
// 用 * 打開ptr位址的變數(也就是a),看裝了什麼
```
----
& 是取址符號
\* 是取值符號

----

----
除了看房子裡有什麼,我還可以換房子裡的內容
```cpp=
int a = 10;
int *ptr = &a;
*ptr = 20;
// 用* 把ptr位址上的房子打開後,把他的內容換成 20
```
----
注意!
int *ptr 跟 *ptr 的 * 不一樣
int* 是型態, *ptr 是把 ptr取值出來。
----
指標總結
* 指標:存放變數位址的型態
* 指標宣告: int* ptr;
* &a: 取a變數的位址
* *(位址): 從位址取值
---
更深入一點
----
之前資料型態的課程有學過,
我們知道int的大小是 4 bytes
```cpp=
int a = 10;
cout << sizeof(a); // 4
```
想像電腦裡的存放空間是一堆格子
也就是,存放整數的那個格子,佔了 4bytes 的大小
----
那存放指標的那個格子大小是多少呢?
```cpp=
int a = 10;
cout << sizeof(&a); // 8
```
也就是存放指標的那個格子,佔了 8 bytes 的大小
----
那存放指標的那個格子,他也有位址嗎?

----
```cpp=
int a = 10;
int *a_ptr = &a;
int **a_ptr_ptr = &(a_ptr); // 指標的指標
cout << "a 變數的位址: " << a_ptr;
cout << "a 指標的位址: " << a_ptr_ptr;
```
---
### 陣列 Array
> 一大排位址連續的房子
----
```cpp=
int arr[4] = {8, 7, 8, 7};
```

----
陣列在跟電腦要位置時,是一起要的,所以他們的地址也會連在一起。
而 arr 就代表一整個陣列的開頭位址。
```cpp=
int arr[4] = {8, 7, 8, 7};
cout<<arr;
cout<<&arr[0];
```
----
為什麼前後位址都差4?
int 的大小?
```cpp=
sizeof(arr[0]) // 4
```
0x7FFEE7009730
0x7FFEE7009731
0x7FFEE7009732
0x7FFEE7009733
都用來存 arr[0]
----
不小心踏入禁地?
Segmentation Fault
(oj會顯示RE runtime error: 執行時發生錯誤)
----
```cpp=
int arr[100] = {1}; // 和電腦要了100個格子
arr[1000]; = 100; // 這不是你的領地,電腦不給你動
// segmentation fault
```

----
what's wrong with this?
```cpp=
int arr[1000];
for (int i=0; i<=1000; i++) {
arr[i] = i;
}
```
---
### 指標的運算
----
陣列的地址在電腦上是連續的。
arr[0] 的隔壁住 arr[1],所以我把 arr[0] 的地址往後加一個就會得到 arr[1] 的位址。
```cpp=
int arr[5] = {2, 4, 6, 8, 10};
for (int i = 0; i < 5; i++) {
cout << "arr[" << i << "]: " << &arr[i] << endl;
}
```
----
另一種寫法:
```cpp=
int arr[5] = {2, 4, 6, 8, 10};
int *ptr = arr;
for (int i = 0; i < 5; i++) {
cout << ptr << endl;
ptr ++;
}
```
ptr++ 直接跳到下一個人的位址。
----
arr[4] 跟 arr[0] 的位址差多少呢?
```cpp=
int arr[5] = {2, 4, 6, 8, 10};
cout<<(&arr[4]-&arr[0]);
```
----
等價寫法
a[i] <---> *(a+i)
&a[i] <---> (a+i)
a 是陣列開頭,i 是往後幾個
----
想一下,這下面的code 在做什麼?
```cpp=
int arr[4] = {1, 2, 3, 4};
for (int i=0; i<4; i++) {
cout<< *(arr+i) << endl;
}
// 等同於
for (int i=0; i<4; i++) {
cout << arr[i] << endl;
}
```
----
想一下,印出的結果是什麼?
```cpp=
int arr[4] = {2, 4, 6, 8};
cout << (*arr + 2) << endl;
cout << (*(arr+2)) << endl;
```
---
小練習1
查詢某一個值有沒有在陣列中,輸出他的所在的index
若沒有,輸出Not Found
https://ideone.com/rgQo9B
----
小練習2
來當個駭客,假裝是管理者登入
[BOF](https://en.wikipedia.org/wiki/Buffer_overflow) 攻擊
https://ideone.com/DXXSgF
----
<img src="https://i.imgur.com/aKKzrHr.png" alt="drawing" style="width:400px;"/>
----
OJ 練習
https://neoj.sprout.tw/problem/1064
{"metaMigratedAt":"2023-06-15T23:56:49.376Z","metaMigratedFrom":"Content","title":"pointer","breaks":true,"contributors":"[{\"id\":\"8b6cb7cf-d748-4d26-bf43-fed5ee1f80a0\",\"add\":4370,\"del\":577}]"}