在撰寫此段說明的時候, 我忘記我已經寫過一遍了, 所以鬧了雙胞, 請參考另外的一份說明:
觀念應該是相同的, 但是解釋的角度和列舉的範例有一些不同, 我也是覺得很奇怪, 同樣的東西怎麼在不同的時間會寫出不同的東西呢? 不管怎樣, 請您多花一點時間欣賞了...
本來高階程式語言中的指標, 也沒人說一定要用記憶體的位址來製作, (C/C++ 語言中為了執行的效率才會這樣子做的), 指標的概念算是讓 CPU 在存取資料時中間多一層的間接緩衝, 例如下面這句話:
對了! 就是為了增加程式的彈性, 所以我們使用間接的方法來存取資料 (或是程式)。
舉一個一般的例子:
在 C/C++ 中為了增進執行碼的效率, 用資料變數在記憶体內的位址 做為指標。 如下節所述。
注意:
int (*iPtr);
如此你更可以瞭解為什麼不另創一個型態叫做 intptr 來定義 iPtr 了。
在 C/C++ 中指標變數要存放的資料是記憶体的位址, 例如:
注意:
相對應上面 "存放資料" 這種使用 iPtr 變數的模式, "讀取資料" 是另一種使用 iPtr 變數的模式, 例如:
除了上面兩種使用方式之外, 指標變數更常看到的使用法是與 * 運算子結合來間接地存取資料變數內的資料, 如下:
這個 x 和在等號右邊或是別的地方出現的 x 是不一樣的, 例如:
上面這個敘述中出現的兩個 x, CPU 在處理時都是去 x 那個變數裡把資料抓出來, 但是前一個敘述裡變數 x 出現在等號的左邊時 (所謂的 lvalue), 就不再是將 x 裡的資料讀出來了。 應該解讀為 CPU 見到等號左邊的 x 時會 "將 x 的位址找到, 以便在設定運算中存放等號右邊計算出來的數值", 再來看看前面的
這個敘述, iPtr1 是個指標變數, 裡面存放著變數 x 的位址, *iPtr1 很明顯地和前面討論 x 放在等號左邊或是等號右邊的情形類似, *iPtr1 放在等號右邊的話, 就是將變數 x 內存放的資料讀出, 但是 *iPtr1 放在等號左邊時, CPU 在由變數 iPtr1 中讀出變數 x 的位址後, 不去讀變數 x 內存放的資料, 而將該位址 (變數 x 之位址) 留下來準備在設定運算中存放等號右邊計算出來的數值。
你也可以把程式中出現 *iPtr1 的地方看成是一個變數, 這個變數是 "iPtr1 變數內記錄的記憶體位址所代表的變數", 在程式編譯的時候 CPU 沒有辦法確定這個變數到底是指哪一個變數, 必須等到程式執行的時候 CPU 才根據 iPtr1 變數內的結果去確定 *iPtr1 這個變數到底是指哪一個, 這樣子的話程式的功能會突然增強了許多,本來 x = 10; 這樣的敘述 在程式執行的過程中永遠只能在一個確定的變數 x 內存放 10 這樣的資料, 現在 *iPtr1 = 10; 這樣的敘述則可以把 10 這個資料存放在很多不同的變數裡, 完全看程式執行到這一列敘述時 iPtr1 這個變數裡存放著哪一個變數的位址來決定。
只要有一個指標內存放的資料錯誤, 根據這個錯誤的指標, 程式可能會損毀更多的資料(包括指標), 如此就像核子反應一樣, 一傳十、十傳百, 程式很快就當掉了。
程式藉由指標指到已經不能使用 (已經釋放掉) 的記憶體。
記憶體沒有釋放掉而又把指標變數的內容毀掉, 導致沒有任何方法去存取此區段之記憶體。
注意:
如果是字元指標的話,
如果是浮點指標的話,
C 語言裡面沒有定義兩個指標 (位址) 相加的運算, 但是有定義兩個相同形態指標的相減運算, 如下:
相當於:
在設計程式的時候雖然你知道這兩種表達方法完全等效, 但是請儘量用陣列的語法, 比較有整體資料的概念。
C語言中使用位址來製作指標使得在 C 語言中可以直接實現 memory-mapped I/O,例如:
注意:
先看看兩層指標的標準用法:
再看看陣列的指標 (pointer to array) 以及二維陣列 (two dimensional array) 的基本用法:
回
程式設計課程
首頁
製作日期: 98/12/05
by 丁培毅 (Pei-yih Ting)
E-mail: pyting@mail.ntou.edu.tw