C/C++ Pointer === 相信很多人都還對指標這定義很不熟悉,甚至在寫程式時也很容易搞混,沒關係小弟也是從這懵懵懂懂的道路走過來的,這邊先直接給一道程式大家先試著想想看答案是什麼?! ```cpp= int main() { int a = 5; int b = a; std::cout << a << std::endl; std::cout << b << std::endl; a = 10; std::cout << a << std::endl; std::cout << b << std::endl; return 0; } // output // a = 5 // b = 5 // a = 10 // b = 5 ``` 小弟本身是先從 python 學起(雖然大學修課是C/C++),如果上面程式來看自己會覺得最後 `a = 10`、`b = 5`,沒錯答案的確是這樣起初剛學指標時也很容易會被這種題目混淆,會思考著 b 到底是獲得 a 的數值還是位址。 接著就是位址、指標的重點了,以下面程式來看當宣告變數時會給予一個記憶體空間去做存放,而這空間就是人家常提到的位址,那 a 這個變數便代表了 `0x0011FF00` 這個位址,而這位址存放的元素為 int 變數(4 個byte)。 ```cpp= int a = 10; int b = 20; int c = 30; ``` ![](https://i.imgur.com/FT8w405.png =300x) 那麼 pointer 要做什麼用呢,當想要去更動位址裡面的數值時 pointer 就派上用場啦,可以應用到的範圍很廣這邊就先講一下他的基本要數,從下面範例來看這次 b 直接取了 a 的位址,那當 b 給予其他數值時(也就表示該位址做更動) a 的數值也會跟著做改變。 ```cpp= int main() { int a = 5; int *b = &a; std::cout << a << std::endl; std::cout << *b << std::endl; *b = 15; std::cout << a << std::endl; std::cout << *b << std::endl; return 0; } // output // a = 10 // b = 10 // a = 15 // b = 15 ``` 那麼先看了上面的 pointer 起手式後,來簡單講解 `*` 與 `&` 做什麼用的,當你宣告變數時該變數名稱只是代表該型態值,也就如下面程式當宣告 a 為 10,那這個 a 變數只是一個 int 型態值有它自己的記憶體空間,所以當你宣告 b 為 a 時就只是將 a(10) 這個值也給 b,那 a 與 b 各為不同記憶體空間。 ```cpp= int a = 10; int b = a; ``` 當想要牽一髮而動全身的效果時就得用到 `*` 與 `&`,如下程式所示,`int *b` 為要放入 int 位址的變數,`&a`為將 a 的位址取出來,所以 `int *b = &a` 為將 a 的位址給予 b,所以 b 拿到的是 a 的位址。 * `*`:為位址變數 * `&`:取變數位址 ```cpp= int a = 10; int *b = &a; // a 位址 0x61fe14 // b 位址 0x61fe14 ``` ![](https://i.imgur.com/TzVDhHz.png =450x) 但要將 b 位址裡面的數值顯示出來該怎麼做呢? `**` 就是將位址裡面的值顯示出來,有點像負負得正的概念 ```cpp= std::cout << a << std::endl; std::cout << *b << std::endl; // a => 10 // b => 10 ``` ## Arrary 剛有提到 pointer 應用場景很廣,這裡就介紹常用到的陣列(Array),陣列與一般變數不同的是陣列可以存很多個變數,也就是說一般變數只給一個記憶體空間,而陣列則是給很幾個記憶體空間,聽起來很繞口直接看程式! ```cpp= int main() { int a = 10; int b[2] = {10, 20}; int c = 30; // testFunction(&a, &b); std::cout << &a << std::endl; std::cout << b << std::endl; std::cout << &c << std::endl; return 0; } // output // a 位址==> 0x61fe1c // b 位址==> 0x61fe14 // c 位址==> 0x61fe10 ``` ![](https://i.imgur.com/Vx0iqQb.png =350x) 這次你有發現 b 不需要 `&` 就能直接顯示位址了耶,宣告陣列本身就是記憶體位址,那麼不就可以直接將陣列位址給其他人了囉!? 請看程式~ ```cpp= int a[3] = {3, 4, 5}; int *b = a; // a 位址==> 0x61fe14 // b 位址==> 0x61fe14 ``` 下面程式有讓你覺得好像有看過類似這樣的陣列操作嗎? 由於 b 本身就是陣列位址,所以可以藉由 `b+i` 的操作來換下一個記憶體位址,再配合上面有提到的負負得正的概念, `*(b+i)` 就能將值取出來囉~ ```cpp= int b[3] = {10, 20, 30}; for(int i = 0; i < 3; i++) { std::cout << *(b+i) << std::endl; } ``` ## 結論 當宣告一個變數就是挪出一個記憶體空間去存放這個變數,那就有了位址與數值的關係。 * `int a = 2`,a 為 int 型態數值,數值為 2 * `int *b = &a`,b 為 int 指標位址,位址為 a 的位址 * a 與 b 位址相同,所以 a 與 b 的存放數值也就相同 * `int c[3] = {10, 20, 30}`,b 為 3 個 int 指標位址,各存放 10、20、30 數值 * `int *d = c`,d 為 int 指標位址,指向 c 的位址