跳到主要內容

Pointer 之不是我排擠你而是我搞不定你!

學習 C 的過程中, Pointer 這個章節對我來說是個無法抹去的痛.
也許是我領悟力太差, 又或許是練習不夠, 我始終無法說服我自己 Pointer 的概念是很自然的.

在 Java 中, 不會操作到指標, 也沒有操作指標的方法.
Primitive Datatype 就是傳數值, Object Datatype 就是傳位址. 雖然骨子裡頭, 物件的操作一樣是使用指標傳遞位址, 但是看不到指標卻是如此的神清氣爽.

在 Objective-C 裡就不是這麼一回事了. Pointer 又回來了.
沒辦法搞定 Pointer 就沒辦法搞定 Objective-C, 不得不, 還是得好好的練習摸索.

於是, 用幾個範例來幫助自己記憶, 分享給所有對 Pointer 沒轍的程式人 orz...
int numbers[] = {1, 2, 3};
int *numbersPtr;
numbersPtr = numbers;
NSLog(@"%i, %i, %i, %i", *numbers, numbers[0], numbers[1], numbers[2]);
NSLog(@"%i, %i, %i, %i", *numbersPtr, numbersPtr[0], numbersPtr[1], numbersPtr[2]);
[輸出結果]
1, 1, 2, 3
1, 1, 2, 3
先複習一下, 宣告變數時, 在變數名稱前加上 "*", 即為宣告該變數為特定資料型態的指標.
使用變數時, 在變數前加上 "&" 可以取得儲存該變數的位址, 可以用來指派給指標.
使用指標變數時, 在變數前加上 "*" 可以取得該指標指向之位址所儲存的數值.
那指標是什麼? 指標是一個變數, 用來儲存某種資料型態之資料的位址.

回到範例, 在這個例子裡頭很明顯可以看到,  以中括號宣告的 int array 可以指派給 int pointer.
又可以看到, *numbers 和 numbers[0] 的數值相同, *numbersPtr 和 numbersPtr[0] 的數值相同.

所以可以推論
=> 陣列是一種指標, 而陣列變數存的其實是第一個 element 的位址.

實際上書裡也是這麼寫的,
numbersPtr = numbers <-equals-> numbersPtr = &numbers[0]
所以 "*" 加陣列名稱實際上取得的是第一個 element 的數值.

看起來, 似乎沒什麼問題了, 根本沒想像中那麼難嘛, 寫程式的人是怎麼回事, 有那麼恐怖嗎?
用到一個 "*" 的時候看起來好像真的沒那麼難, 那如果用到兩個 "*" 呢?
老實講, 我頭好暈 orz...

最簡單的就是在 Objective-C 中的 Object Datatype. 換個例子再看看.
NSString *string1 = @"String1";
NSString *string2 = @"String2";
NSString *strings[2]; //an array of NSString objects
strings[0] = string1;
strings[1] = string2;
NSString **stringsPtr; //a pointer to NSString object 
stringsPtr = strings;
NSLog(@"%@ %@ %@", *strings, strings[0], strings[1]);
NSLog(@"%@ %@ %@", *stringsPtr, stringsPtr[0], stringsPtr[1]);
[輸出結果]
String1 String1 String2
String1 String1 String2
要先說明的是, 在 Objective-C 中物件的宣告和 Java 不同, 必須用到 "*".
但問題來了, 該怎麼取得物件的內容呢?
如果依照 Primitive Datatype 的概念, 第一個想到的答案會是使用 "*" 加上物件名稱, 然而這樣的操作方式, 並不能取得該物件的內容. (那會取得什麼呢? 有興趣可以自己玩玩看 XD)
取得物件的方式和 Java 沒兩樣, 不需要加上 "*", 直接使用物件名稱就可以取得物件的內容.
那麼, 怎麼進行物件的指派呢? 這也和 Java 一樣, 不需要加上任何符號, 直接以物件名稱就可以進行指派. 說明結束, 回頭看範例!

在這個範例中, stringsPtr 這個變數有兩個 "*".
別和我一樣一看到兩個 "*" 就暈了. 冷靜想想, 兩個 "*" 並沒有那麼恐怖. 因為在 Objective-C 中物件的宣告必須使用到 "*", 所以 stringsPtr 的宣告實際上是這個意思
=> 宣告 stringsPtr 為一個指向 NSString 物件的指標.

剩下的其實就跟第一個範例一樣, 陣列就是一種指標
=>  strings 這個 NSString 物件陣列, 可以指派給 stringsPtr 這個 NSString 物件的指標.
陣列名稱存放的其實是第一個 element 的位址
=> "*" 加陣列名稱將會取得在陣列中的第一個物件.

呼... 看似簡單, 但每次用上卻依然覺得頭昏眼花.
真的希望是熟練度的問題, 希望在我多多練習後, 不會再次碰上 Pointer 指向哪, 看了程式碼卻越看越花的窘境.

留言

這個網誌中的熱門文章

誰讓你心動, 誰讓你心痛, 誰會讓你偶而想要擁他在懷中... 誰又在乎你的夢, 誰說你的心思他會懂, 誰為你感動... 許久沒聽到這熟悉的詞與曲, 更懷念那甜美細膩的好嗓音. 於是趁著空檔, 拿出了放在那如同收藏我的回憶般, 收藏櫃子裡頭的兩張專輯.

引數?! 參數??!! 什麼鬼啊!!

我想這個不僅是只有我會遇到的問題, 大概也是所有 Programming 的人都有的疑惑 (應該是吧?) 什麼引數?? 什麼參數?? 天啊... 到底是誰翻譯的呀!!!! 就字面上來看... 講句實在話, 我真的不了解, 大概是學藝不精所致. 也許有些人認為 => 管它那麼多!! 寫得出來就好了!! 不過龜毛如我, 我還是想搞清楚定義是什麼!

關於 Objective-C 的基本功

就在 iPhone 開創了智慧型手機軟體市場後, 市面上出現了很多關於 iPhone 平臺的開發教學書籍. 但是, 關於 iPhone 使用的程式語言 Objective-C 的書呢? 這種練基本功的書籍卻是少得可憐. 而龜毛如我, 只曉得怎麼使用 Cocoa framework, 卻不曉得基礎程式語言怎麼運作, 老是覺得渾身不自在. 就在打算入手 "Programming in Objective-C 2.0" 這本英文書的同時... 我發現 => 中文版出了!!!! 這對要使用 Objective-C 來寫程式的我, 無疑是一種福音. 無論是在價格上, 或使用的文字上. XDDD~