- 1. variable - 變數
- 恩..變數...沒什麼好說的 XD
- 2. pointer - 指標,指向某個變數的記憶體位址
- 在指標變數裡存的是一個位址 (address),它可以指向某個變數,可以透過 * 運算元間接存取該變數;而要取得某個變數的記憶體位址,則是使用 & 運算元。
-
- (1) 初始化
- 指標變數的初始化是相當重要的。宣告後未經初始化的指標變數會發生悲劇 XD。其實應該這麼說,使用沒有初始化的指標變數不僅毫無意義,而且還會發生不可預期的錯誤。
- 把指標變數想像成遙控器的話,它所指向的變數就是這支遙控器可以控制的對象。顯而易見的,我們必須清楚知道我們控制的是什麼東西,這樣的操控才有意義,好比說,把遙控器設成控制自己家的小狗 (如果可以的話),然後叫牠去把門口的報紙拿進來、順便泡杯咖啡之類的 (我根本在癡心妄想 XDDD)。
- 好啦言歸正傳,如果少了「設成控制自己家的小狗」(也就是初始化) 這個動作,就直接拿著遙控器亂按,如果跑進來的是一隻恐龍還是蟑螂誰要負責 XDDDD。聽我在亂講,不會有奇怪的東西跑出來,只是程式可能會 crash 而已。
-
- int var;
- int *ptr;
- *ptr = 0; // dangerous!! (但 compile 會過)
- ptr = &var; // 把 ptr 指到 var 這個變數
- *ptr = 3; // 這個指令會把 var 設成 3
- (2) 型別
- 變數有形別之分,但是指標長得都一樣,這邊所謂的指標型別,說的是這個指標指向的變數的型別。
- 比如說 int 是 4 bytes,那麼指向 int 變數的指標意義就是:從指到的位址開始往後算 4 格是這個指標變數所配置到的記憶體範圍 (我應該畫圖的,可是好懶 >"<);char 是 1 byte,那麼指向 char 變數的指標配到的記憶體範圍就只有指到的那格;double 是 8 bytes,所以會配到 8 格。
- 雖然指到的位置可能都一樣,但是意義不一樣,所以如果型別混用的話,也是會 compile error 的。
-
- int var;
- int *ptr1 = &var; // correct,ptr1 指到 var
- double *ptr2 = &var; // compile error,double* <== int*
- 雖說如此,想要有個指標變數可以指到任意型別,也是可以辦到,用 void* 就行了。只不過如果用 void* 的話,在使用時要十分注意型別是否正確,否則可能出現不可預期的錯誤。
-
- void *ptr; // 一個 void 型別的指標
- ptr = &var; // correct
- *ptr = 0; // correct,但要小心這裡一定只能 assign int 的值
- (3) 指標的加減
- 延續上面說的型別,對一個指標變數做加法或減法,不同型別的指標變數會有不同的效果,因為指標的移動是以型別的 size 當單位的。
-
- int iArr[10];
- int *iptr = iArr; // 把 iArr 的開始位址 assign 給 iptr
- iptr++; // iptr == &iArr[1],實際上移動了 4 byte
- char cArr[10];
- char *cptr = cArr; // 把 cArr 的開始位址 assign 給 cptr
- cptr++; // cptr == &cArr[1],實際上移動了 1 byte
- void 不屬於任何一個型別,所以對 void 型別的 pointer 做加法或減法會 compile error。
-
- void *ptr = iArr;
- ptr++; // compile error!!
- 還有關於運算元的 priority 的部分,用 * 取值的 priority 低於 ++ 的 priority,因此下面兩個的意義是不同的
-
- *ptr++; // 取值之後把 ptr 往後移一格,相當於*(ptr++)
- (*ptr)++; // 把 ptr 指到的內容加 1
- 另外還有多重指標,像是 **ptr 什麼的,就不在這邊說了。
- 3. reference - 變數的別名 (alias)
- reference 和 pointer 一樣,可以用來間接存取變數。如果把 pointer 想成遙控器的話,在這邊可以把 reference 想成...替身吧。不同於 pointer 可以指來指去 (assign 不同變數的位址給同一個指標變數),一個 reference 在程式裡面是不能被 assign 成其他變數的替身。也就是說呢,一旦決定當誰的替身了,就會永遠變成那個變數 (這是不可逆的化學變化啊啊)。
- 正因為它不能被 assign,所以宣告的時候就要同時初始囉,不然 compile 不會讓你通過 (You can not pass!!!)。
-
- int var, var2 = 10;
- int &ref1 = var; // correct,把 ref1 當作 var 的替身
- int &ref2; // compile error,沒有初始化
- 從此之後見 ref1 如見 var !!!有關 reference 的使用
-
- ref1 = var2;
- 上面那個指令會讓 var 的值變成 10 (也就是 var2 的值),相當於
-
- var = var2;
- 這個指令,而不會再把 ref1 變成 var2 的替身噢。
- 而下面這個的話
-
- ref1 = &var2;
- 明顯就是 compile error 噢!哪有人把 int 指標直接 assign 給 int 變數的呢!
- 4. pointer reference - pointer 的替身
- 其實這應該是要來把大家搞混的 @@。根據字面上的意義呢,它是一個 reference,而這個reference 是一個 pointer 的替身。
-
- int *ptr;
- int *&refPtr = ptr; // refPtr 是 ptr 的替身
- 這要幹嘛呢?我猜大概就是為了彌補 reference 不能動來動去這件事吧。雖然 refPtr 只能代替 ptr,但是 ptr 本身可以動來動去,所以可以指到不同的變數。不知道實用性如何,不過我相信必然是很容易搞混的。
- 還有就是,我剛剛試過了,沒有 reference pointer (也就是指向 reference 的 pointer) 那種東西 XD
就一個 ACMer 的角度來說,pointer 這東西是少碰為妙。因為如果沒有很清楚的話很容易出錯或浪費時間,在比賽的時候浪費時間是罪過啊!所以 pointer reference 就更不用說了,看看就好,被搞混之後就可以忘記了 XDD。
噢沒有啦,還是要知道一下 (才不會顯得無知!?),只是強烈建議不要拿來用啦,根本找自己麻煩 ˊ _>ˋ。
No comments:
Post a Comment