###### tags: `sprout` # pointer clang 2021 廖凰汝 --- ![](https://i.imgur.com/E9kBmrs.png) ---- ![](https://i.imgur.com/BgdpK1b.png) ---- ```cpp= int a = 10; ``` 當宣告一個變數,會將他放在電腦的某一個位置 ![](https://i.imgur.com/n8gupEg.png) ---- ```cpp= int a = 10; ``` 當宣告一個變數,會將他放在電腦的某一個位置 ![](https://i.imgur.com/Yq8xFRi.png) ---- 怎麼知道變數在電腦的位址是什麼? ![](https://i.imgur.com/oTcwM6Z.png) ---- ```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; ``` ---- 回到房子的例子。 如果我們知道房子的位址,想知道裡面的值? 我們需要一把鑰匙。 ---- ![](https://i.imgur.com/CobPIux.png) ```cpp= int a = 10; int *ptr = &a; // ptr 存變數a的位址 cout << "a的內容是什麼?" << *ptr; // 用 * 打開ptr位址的變數(也就是a),看裝了什麼 ``` ---- & 是取址符號 \* 是取值符號 ![](https://i.imgur.com/rvqC2d2.png) ---- ![](https://i.imgur.com/spDbFhN.png) ---- 除了看房子裡有什麼,我還可以換房子裡的內容 ```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 的大小 ---- 那存放指標的那個格子,他也有位址嗎? ![](https://i.imgur.com/HHfyS1f.png) ---- ```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}; ``` ![](https://i.imgur.com/KP4saqE.png) ---- 陣列在跟電腦要位置時,是一起要的,所以他們的地址也會連在一起。 而 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 ``` ![](https://i.imgur.com/uyW48uN.png) ---- 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}]"}
    517 views