C語言: 超好懂的指標,初學者請進~ - 寫點科普Kopuchat
文章推薦指數: 80 %
等等,那C 語言中的指標是長什麼樣子? 讓我們來看看這段程式碼: void main(){ int a = 15; int b = 2; int c = 39; ...
跳至內容
程式教學>C/C++
內容目錄
什麼是指標(Pointer)
指標變數(Pointervariable)
程式教學>C/C++
內容目錄
什麼是指標(Pointer)
指標變數(Pointervariable)
指標(pointer)這個功能在C語言中有著非常重要的地位。
C語言中特有的指標,可以透過記憶體映射的方式直接控制硬體,這也是為什麼C語言在硬體系統特別強大的原因,包括資料結構(陣列/字串/鏈結串列)、系統程式(編譯器/作業系統)、演算法,都會進一步使用到。
但對於初學者來說,一開始無法釐清指標、導致後續指來指去,指到最後往往變成噩夢。
今天我們的目標,就是從頭開始把指標介紹的非常簡單。
什麼是指標(Pointer)
這張照片叫「MilkyWayandStarryNightSky」,是一張看著便賞心悅目的美麗星空圖,當桌布做美工都適合。
如果你想要這張照片的話,最直接的辦法就是我給你這張照片的網址「https://www.goodfreephotos.com/astrophotography/milky-way-and-starry-night-sky.jpg.php」,讓你在網址上拿到這張照片。
這和指標有什麼關係呢?概念很類似噢!只要我給你這個網址,你就可以藉由這個網址拿到這張照片,也就是說網址是指向這個資料的「指標」。
哦~原來資料的地址就是指標嘛,是不是非常簡單的概念呢?
等等,那C語言中的指標是長什麼樣子?
讓我們來看看這段程式碼:
voidmain(){
inta=15;
intb=2;
intc=39;
intd=180;
inte=67;
}
在這個程式碼中,我們宣告了五個變數。
以intb=2為例,在宣告好變數、程式開始執行後,會去記憶體中要一塊儲存空間,然後把2這個資料放進去。
還記得我們說過記憶體就像一個大櫃子、每個格子都有相對應的地址嗎?這個2的地址就是在記憶體中的某一個地方。
但我們說過,記憶體中一個格子的大小是1個byte,而一個int(整數型)的大小就占了4個byte,所以這邊寫的地址,是2這個整數所占的這一塊記憶體空間的起始地址。
從起始地址開始起算、共佔了4個格子,也就是4byte。
也就是說,當我們宣告一個變數時,總共會有三個要素:
程式會向記憶體要一塊空間來儲存變數值,所以這個儲存空間有一個起始位址。
再加上這個變數的名稱(b)與變數值(2)。
通常我們會把變數的位址,稱為「指向該變數的指標」。
在這邊需要特別注意的是,我講的是「指標」,而不是「指標變數」;這兩個是不同的東西。
拿一開始的照片作為對照例子,是不是很清楚呢?
但我們在宣告一個變數,比如宣告b的時候,要怎麼知道到底是跟記憶體要了哪一塊地址放這個b呢?怎麼樣才能看到這個變數的位址?
這邊就要介紹一下在C語言裡面,有個運算符號是用來「取址」,就是「&」。
怎麼做呢?請參考以下程式:
#include
從0x7fff54a109c8開始的4個byte都是b所配置到的記憶體空間,儲存了2這個值。
這時你一定想問:有地址要做什麼?我們宣告完變數後也用得好好的,沒事要它的地址幹嘛?
事實上我們拿到一個地址,都是為了要去到這個地址上、以抓取上面的變數。
(知道了朋友的地址,目的不就是要去拜訪他嗎?或就像我們利用網址去抓照片一樣)
但問題來了,怎麼樣能利用一個變數的地址、去拿到這個變數呢?直接把地址寫出來然後執行嗎?
答案是不行的。
我們要利用C語言中的另一個運算元「*」來做這件事。
#include
事實上,「*&b」和「b」的意義是等價的。
指標變數(Pointervariable)
講完了什麼叫指標後,接下來讓我們看看「指標變數」。
還記得我們說過,指標(Pointer)就是某變數的位址。
而這邊的指標變數(PointerVariable),則是用來存放指標的變數。
案例中的pointer就是一個指標變數。
變數都是用來存放「值」的,而整數型變數int就是存整數、字元型變數char就是存字元。
所以這個指標變數就是用來存「地址」的變數。
也就是說,宣告一個指標變數,和一般宣告變數一樣,是跟記憶體要一個區域、存放這個變數的值。
只是這個變數的型別是指標。
另外,由於pointer中存的地址是變數b的值,因此我們又把pointer稱為「變數b的指標變數」。
這些概念非常的簡單,只是一定要弄清楚。
接下來你可能會問:要怎麼去宣告一個指標變數呢?
我們可以採用「*」這個運算符號。
int*pointer
pointer表示這個變數的名稱,而*表示pointer這個變數是個指標。
等等,那int代表什麼意思?星星符號運算元*不就說是個指標了嗎?
int代表這個指標變數指向的變數的類型。
…你在說什麼在繞口令嗎?
直接看下圖吧!
具體來說的程式碼長這樣:
intb;
//跟記憶體要一塊區域稱為b,這塊區域專門放int型變數值
b=2;
//把2這個值給變數b
int*pointer;
//跟記憶體要一塊區域稱為pointer,這塊區域專門放指向int型變數的指標(地址)
pointer=&b;
//把變數b的地址值給pointer,注意不能寫成pointer=b;
還記得「&」代表「把這個變數的地址取出來」的意思嗎?要注意,這邊絕對不能寫成pointer=b;,因為pointer是專門存放地址的變數。
如此一來,我們就稱「指標變數pointer指向了變數b」,是不是很好懂呢!
很多書上寫的有些模糊,初學者又還搞不清楚時,就會導致指標、指標變數、指標變數宣告等產生混亂。
接下來還想問個問題:能不能利用pointer去拿到它指向的b這個變數呢?當然可以。
這邊同樣要利用到*這個運算符號。
當我們跑完這個程式碼之後:
intb=2;
int*pointer=&b;
會發生這件事:
也就是說變數b在記憶體中對應了一塊儲存空間,而這塊儲存空間總有一個起始的地址。
所以pointer對應到的就是這個起始地址。
在這種狀況下,就可以用「*pointer」來拿到這個變數。
這裡的「*」,和宣告指標變數的int*pointer的意義不太一樣。
反而是和「&」相對應——「&」代表「取出地址」、「*」代表「取出內容」。
等等,那所謂的「*pointer取出的內容」指的到底是變數b、還是變數b的值2?
這兩個是不同的東西喔!變數b是這塊區域,2是值。
答案是:*pointer代表的就是變數b。
所以我們可以把*pointer當作變數b來使用。
直接看程式碼吧:
#include
然後用「&b」取出變數b的地址為「0x7fff551b49c8」。
由於&b的值被賦予給pointer,所以把pointer印出來後同樣也是「0x7fff551b49c8」。
由於我們說過*pointer就是其指向的變數b,所以在這邊我們試著把*pointer中的值改成100,然後印看看原有的變數b會不會跟著改變。
發現會欸!2被改成100了!
最後,由於存放pointer這個變數的地址,和變數b的地址不一樣,所以利用「&pointer」後,可發現地址「0x7fff551b49c0」和變數b的地址果然不一樣。
試著寫個小程式玩玩看:
#include
延伸文章資訊
- 1C語言: 超好懂的指標,初學者請進~ - 寫點科普Kopuchat
等等,那C 語言中的指標是長什麼樣子? 讓我們來看看這段程式碼: void main(){ int a = 15; int b = 2; int c = 39; ...
- 2第5章、陣列和指標 - C/C++
但是有三種應用場合,使用指標仍然是必要的。第一是字串(string)的宣告;第二是動態記憶體配置(dynamic memory allocation);第三是函式的 ...
- 3C++ 入門指南- 單元4 - 指標與參考 - 程式語言教學誌
指標(pointer) 儲存變數(variable) 的記憶體位址(address) ,參考(reference) 則是變數的別名(alias). *nPtr &nRef. C++ 中,除了基本...
- 4(C) 簡單搞懂指標(pointer)、指標陣列(pointers of array, int *foo ...
a) *ptr++是表示*(ptr++)的意思,就是ptr指向下一個位置所存的值(同arr[i++])。 b)*++ptr是代表ptr先做位址往前移,再取值(同arr ...
- 5指標與位址 - OpenHome.cc
int *n; float *s; char *c;. 雖然宣告指標時,C 習慣將 * 前置在變數名稱前,不過 n 的型態是 ...