我們從機械語言定址法說起好了
絕對定址法:
比如,從位址 0x300 取出值,放入累加器
間接定址法:
比如,從位址 0x300 取出值,這個值又當成位址,再去該位址取出其值,放入累加器
組合語言應該是不會那麼三八,給你兩層三層的間接定址的
但 C 語言可以,每多打一個星號取出其值,就是取出的值再間接定址一次
但事實上還不是湊出來的 :P
前面說了,值取出後放入累加器
那我就把累加器的值不當值,當成位址,再取一次就好啦
在機械語言裡這麼直觀的東西
在 C語言裡,說"為了你方便",有點不一樣
0x300+1 是多少? 0x301 嘛,對吧~
但如果在 C, 就會說指標指的物件是有 size 的
如果是個 word, 那麼 0x300 + 1(word) = 0x302
也就是那個 1,必需賦與單位,單位是 word
就這樣而已,差別不大 XD
但這在陣列裡算好用的
比如一個 size = 32 byte 的元素
0x300 + 1(32byte) = 0x320
在陣列就真的好用
要把 0x300 當數值用時,比如當 word, 其實就是 (word)0x300
就算它本來是指標,也會被 cast 成 word
要把 0x300 當指標用時,就算它本來是word, 只要你 cast 下去,就會變指標
(void*)0x300 像這樣,它就變指標
一般來說,我們不胡搞,以免自己受不了
可是當你在看別人程式時,你無法禁止別人胡搞
如果跨模組時,直接胡搞更是把不同模組黏起來最快的方法
就像拿全域變數寫程式一樣,又爽又危險 XD
所以就算本來宣告 int ***a; 說 a 是個三層指標好了
可是我要用時,馬上 cast (int**)a 這樣用
你受不了又怎樣呢?就是可以 XD
一個變數要被視為什麼,是要'活在當下'的
當下怎麼用它,它就是什麼
如果你不確定,就多步進執行或加 print 去看它
而因為指標的加一減一,事實上是帶單位的
所以記得 sizeof 偶爾要用用,去檢查檢查它是不是你所想的那麼一回事
回到 怎麼學能學好
你要故意學很高深當然可以,就好像學生時微積分學到很難,出社會後好像沒在用
你常用的程度自然就會熟了
我是蠻愛用指標的,因為它可以創造物件的分身
寫程式時要注意本尊只有一個,其他都用分身
這樣的好處是不用注意物件的 sync 問題
比如, a=3 , b=a, 然後 a=4
b 是拷 a 的值,但 a 改成 4 之後,b 卻沒一起改
這就是複製的缺點
用分身的話,a 的改變,b 不用通知也會跟著變,多好...
而一堆人都要用變數,到底把本尊放在哪好?
那就是程式架構的問題了
本尊一定要最早產生,最後消滅
如果沒這特性,比如上面的 a 先消滅,b 又保留 a 的值要繼續使用
那 b 不就從分身轉而為本尊的地位?
這麼複雜的擁有權轉移,很容易讓人暈頭轉向的
但也不是絕對不做;觀念清楚就可以
於是我們漸漸會確立物件是個有形有質的'東西'
要好好保管,或好好轉移擁有權
這有形有質的概念堅持下來,物件導向就很有感覺
物件導向不是 class, private, public, method 這些字眼而已
它就是把一群變數好好的當成物件去保管,以有形有質去對待它
有這概念,就算用 c 都可以寫出物件導向
我第一次寫二元數排序,照著課本做就失敗了
後來連續做兩次都失敗,但我確定校對兩次,絕對沒打錯
結論很簡單:課本印錯了,誤人子弟 XD
(第一次成功,就是拋開課本,自己寫就成功了)
若再加上硬 cast 指標以讓程式會動的這些 code
可以說糊成一團粥的機率大增
那還是會自己檢查指標比較重要
檢查下去你就知道那些指標運算在幹麻
像 COM 的巨集裡也在運算指標,我看了就很暈
但拆開來步進一下就懂