--- GA: G-RZYLL0RZGV --- ###### tags: `大一程設-下` `東華大學` `東華大學資管系` `基本程式概念` `資管經驗分享` 指標 pointer 基礎認識(一) === [TOC] ## 前言 指標可以說是 C++ 的超級大魔王,指標變數怎麼指、到底指到誰身上、記憶體位置到底存誰的,概念是有點難理解的,到了大四我仍沒辦法完全搞懂他,但我一定會盡全力把該學到的講給你們聽,同時去看 reference 多參考網路上多位大神的解釋會更好。 <span style="color:red">**參考資料二非常建議閱讀!!**</span> ## 講解影片(還沒錄) {%youtube youtubeid %} ## 基本觀念釐清: 何為變數、何為變數值、何為指標、如何取址 > <span style="color:red">**甚麼樣的資料型態(變數型態)存什麼樣的資料,這個大前提請千萬不要忘記**</span> ### 變數 變數由四個最重要的東西所組成,分別是變數型態、變數值、變數名稱、變數位址,請看以下表格與說明。 | 變數型態 | 變數位址 | 變數值 | 變數名稱 | | -------- | -------- | -------- | -------- | | int | 0x6ffe08 | 9 | a1 | | string | 0x6ffe00 | Orange | s1 | | double | 0x6ffdf8 | 7.3 | d1 | | float | 0x6ffdf4 | 6.5f | f1 |  * 變數位址 * 在你程式執行後,變數儲存在記憶體的位置 * 變數值 * 該變數儲存的值,int 存整數,string 存字串 * 變數名稱 * 使用者對變數做一個自定義名字的動作 而根據你的型態不同,所需的記憶體用量也不同,以整數為例,一個整數就是佔 4 bytes 的空間。 ### 指標 變數位址負責讓你找到你的這個變數在電腦的哪裡,而**變數位址就是變數的指標**!簡單的說,變數的位址就是「**指向該變數的指標**」。<span style="color:red">**這句話很重要!!**</span> **而這邊說的是指標,而不是指標變數,請不要把兩者混為一談哦!!!** ### 取址與參考變數大不同!! 那既然我們這麼大費周章地跟你說了變數位址,自然就是可以被拿來用的東西,未來我們可以親自的來操控記憶體,那既然要操控,我們就要取得他。 要做到取得記憶體位址,需要利用取址運算子「`&`」,透過在變數前面加上這個符號以取得變數的記憶體位址。 * <span style="color:red">**要取得位置,取址運算子請一定是與宣告分開的哦!**</span> ```cpp= int a = 5; cout << &a; //印出 a 的記憶體位址 ``` * <span style="color:red">**請注意,請千萬不要像下面這樣寫!!!**</span> ```cpp= int &a = 5; // 程式會報錯,Error ``` 還記得我們有教過如何宣告參考變數 (reference variable),你可以為變數取一個別 名,所以你在變數宣告的時候這樣寫,是告訴程式說你宣告一個參考變數,並不是取 得一個變數所在的記憶體位置哦! 然而上面這樣寫也不是正確的參考變數宣告,參考變數是為「一個變數」取別名,然而你指派常數給他,是錯誤的,參考變數的宣告一定要接受「變數」,像這樣。 ```cpp= int a = 5; int &a_new = a; ``` ## 何為指標變數(pointer variable)? 上面都可以的話接下來來真的談談指標變數吧! 前面已經強調,指標(pointer)就是某個變數的記憶體位址,而指標變數(pointer variable),則是「用來存放指標的變數」。 有點文字遊戲對吧,所以我們先從前面來。 ``` 整數變數儲存整數 浮點數變數儲存浮點數 字串變數儲存字串 字元變數儲存字元 ``` > 那指標變數儲存甚麼? > 儲存指標!!! > [name=Orange] ### 如何宣告、初始化、設值給指標變數 如果對於指標變數儲存的東西到底是甚麼你已經理解了,接下來來看看如何宣告他。 * 全新符號 `*` ,其有兩種意義 * **指標** * 在**變數宣告**時出現,是**為了宣告指標** * 告訴程式此變數是一個「指標變數」 * 其內容存的是一個記憶體位址 * **取值運算子(Dereference operator)** * 在**宣告以外**的場合出現,是**為了取出指標所指向的位址的值** * 依照變數所存的記憶體位址,去那個位址把資料取出來 ```cpp= int a = 5; // 假設位於 0x6ffe0c int *p1; // 宣告不給值,之後才給值 p1 = &a; // 把 a 變數的位址 0x6ffe0c 存到 p1 內 **-----------我是分隔線------------** int *p1 = &a; // 宣告即給值,把 a 變數的位址 0x6ffe0c 存到 p1 內 ``` 指標變數的宣告方式呢,是在變數型態跟名稱中間加上一個 `*` 號,這樣就是宣告指標變數,而因為他必須接受一個記憶體位址,所以你只能要傳位址給他。 透過上文我們已經知道指標變數儲存指標,而指標又是指一個變數的記憶體位址,所以對於 p1 這個指標變數,就是存變數 a 的記憶體位址。示意圖如下:  而今天一個變數如果他被宣告,他會需要記憶體去儲存他,所以指標變數本身需要一個記憶體,而他裡面儲存的是一個指標(記憶體位址)。 > 學這邊真的在玩繞口令... > [name=Orange] ## 如何取值? 取出誰的值? 針對一般的整數變數、字串變數,要取值時我們都只要打他的名字即可,指標變數也同理,如果要取出他儲存的變數值,也是打他的名字。 ```cpp= int a = 5; cout << "[整數]變數 a 所儲存的[整數]: " << a << endl; //印出 a 就是一種取值了哦! cout << "[整數]變數 a 所處的記憶體位址(也就是指標): " << &a << endl; int *p1 = &a; cout << "[指標]變數 p1 所儲存的[指標](指標變數存記憶體位址): " << p1 << endl; cout << "[指標]變數本身所屬的記憶體位址: " << &p1 << endl; cout << "[指標]變數 p1 所儲存的[指標]指向的值: " << *p1 << endl; ```  相信看到這裡你已經知道我們說的指標變數取值是取出誰的值了!**就是指標變數所儲存的指標指向的值!!!** 用一張圖可以這樣解釋(紅筆對紅筆,藍筆對藍筆)。  最後一個最重要的提醒,<span style="color:red">**指標**</span>跟<span style="color:red">**指標變數**</span>是兩個<span style="color:red">**完全不一樣**</span>的東西,請你一定要搞清楚,不然進入雙重指標就再見了哦! > 指標是_________? > 指標變數是__________? > 大家自己填空想想看吧,忘了麻煩一定要往上回去看! > [name=Orange] ## 小總結整理 * 指標的宣告 * type *name; * type *name = address; * type *name1, *name2, *name3; * 指標的取值 1. 指標變數如同一般的變數,取值就是打名字(取出這個指標變數儲存的位址(指標)) * name 2. 存取指標變數儲存的位址所指向的記憶體空間所儲存的值,<span style="color:red">**在前面加上米字號,切記與宣告不同!**</span> * *name * 如何取址 * 在任何的變數面前加上 `&` * 切記不能在宣告的時候加 * 可以把一個指標變數儲存的指標給另一個指標變數 * `name1 = name2` * 把 name2 指標變數儲存的記憶體位址也給 name1 所以現在兩個指標變數內都存相同的記憶體位址 ## Reference 由淺入深 <span style="color:green">**越上面越簡單**</span> [參考 - 1](https://openhome.cc/Gossip/CppGossip/Pointer.html) [參考 - 2 雖然是用 C 語言(不是 C++),但概念一模一樣,可專注在內文](https://kopu.chat/c%e8%aa%9e%e8%a8%80-%e8%b6%85%e5%a5%bd%e6%87%82%e7%9a%84%e6%8c%87%e6%a8%99%ef%bc%8c%e5%88%9d%e5%ad%b8%e8%80%85%e8%ab%8b%e9%80%b2%ef%bd%9e/) [參考 - 3](https://vinesmsuic.github.io/2019/08/14/c++-pointer/#const%E6%8C%87%E9%87%9D-const-pointer) 比較難的參考資料 [丁培毅老師](http://squall.cs.ntou.edu.tw/cprog/materials/Pointers2.html)
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.