指针—老顽童
??? 《忠犬八公》里面說八公的智商相當于六七歲的頑童,周伯通是一個頑童。只是他的年齡不好估計,不過超過10歲的還能是頑童么?好吧,小于10歲,大于7歲,成熟點。大凡這個年齡段的頑童總是讓人又愛又恨。頑皮的可愛,可愛的頑皮。能干的事兒不好好干,不能干的事兒卻時時逞能。而且在往往之間會做出令所有的人都驚異異常的事情,不喜歡按照常規(guī)出牌,不走尋常路,不想平常人所想,這就是頑童。這就是c語言中的指針!左右互博、空明拳,一直到最后的返老還童這都是指針的絕活。
??? 指針為什么能有這么大的能耐呢?這個我們得從c標準草案中對指針的描述說起,在c標準草案中對指針的描述是:“A pointer type may be derived from a function type, an object type, or an incomplete type, called the referenced type. A pointer type describes an object whose value provides a reference to an entity of the referenced type.”。用我那蹩腳的英文翻譯就是:“指針類型可以脫胎自函數實體、對象實體、甚至是一個沒有定義的實體。但是通過它的值則肯定可以找到他所引用的對象實體。”
??????? Ok。標準里面這段話的描述的其實就是對“空明拳”的英文表述。不信我們可以看看老頑童對空明拳總決的說法“以空而明,以虛擊實,以不足勝有余”。啥意思?意思就是因為什么都不是,所以什么都是;因為沒啥用處,所以用處多多。對比指針,我們看到的是指針的值可以標識任何東西,無論這個東西是函數,實體還是其他什么沒有定義的東西。但是總是能夠通過它來找到他要表示的對象。
????那么指針要怎么做才能通過它的值來找到他所引用的實體呢?最簡單的方法就是給每個實體都編個號,然后通過指針的值來記錄這個號,然后就可以通過這個號來找到實體了。嗯,不錯這個想法不錯。就這么干。那么一個系統中有多少需要標識的實體呢?2的8次方個?不夠吧,但也能用;2的16次方呢?64k個,還是有點少,不過既然256個我們都能忍受,64k用用也無妨;2的20次方呢?1M個,曾經看來是不多也不少剛好,可是咋看著那么怪呢?怪不怪不要緊能用就行,于是我們也用了好多年,直到現在有些地方還在用;2的32次方呢?4G!嗯。這次應該是夠用了,于是在好多年中我們都在用4G個標識符來標識我們在計算機世界中創(chuàng)造的各種各樣的奇奇怪怪的東西。
???? 可是bt的人們總是在創(chuàng)造需求,比如說我要看DVD,還是高清D9的那種,這時候就會發(fā)現d9的影片至少有了4G以上的東西,這種情況下2的32次方雖然足夠大但也是不夠啊,看來還得擴充;2的64次方?步驟化的思維就給出了這么一個步驟化的解決方案了。聽起來很合理,可是用4g來標識計算機世界里面的實體已經持續(xù)了太久太久的時間了,在這漫長的歲月中我們使用4g來作為標識總數的計算機家族已經是家大業(yè)大了,已經不是會為了一個d9而作出太多的改變的龐大家族了。--編外語:可惡的舊勢力啊。總是那么反動。
??? 于是在唾罵之余就有了使用兩個32位整數來湊活的標識大于4g的解決方案,反正cpu足夠快不在乎多讀一次。你咬我啊。這種解決方案雖然惡心,但是可行,所以在各家的os上面就紛紛出現了類似lseek之類的變通方案,雖然不爽,但是省的到處罵仗,就這么憋著,也能用。誰會為一個d9去做太多的改動啊。可是有了開頭的就有后續(xù)的,架不住超過4g表示的物件越來越多啊。終于在沉默中有人爆發(fā)了,終于有一個憋不住的叫AMD的家伙出來罵街了,偏要用64位,而且還就造出了直接支持2的64次方個標識的cpu。于是我們就看到了一些支持64位的軟件就有了AMD64的標簽。指針能標識多少個實體就? 在這罵街聲中多少達成了共識,定為2的64次方個。空明拳的基本框架就這么練成了。
???? 標識數量的問題是解決了,可是標識號的規(guī)則呢?因為我們總是要根據標識號來找到標識內容的啊。關于這個話題,懶人總是有最簡單的法子,法子就是我們把內存位置按照Byte(一般認為是8bit,能表示256個數字)大小一字排開從0開始編號,這樣我們的實體只要在內存中,我們都能知道這個實體的所在的起始位置的編號,通過這個編號就能找到這個實體。方便,真是方便啊。不過我們要人性化,計算機中找實體要通過編號,現實中找人要地址。編號和地址無非是表述不同,本質都一樣的。好,那我們就把這個編號叫地址吧,計算機中的內存地址!
???? 俗話說“龍行一步,鱉爬半年”,什么都能表示,什么都能找得到的指針,在靜態(tài)情況下是多大?步進一步又是多大呢?不著急,我們到了討論老頑童的第二項絕技左右互博術的時候了。左右互博術不能增長功力,不能增長招數,但是能增加技能點,而且是成倍的增加技能點。
??? 那么閑話少說,我們一起來看看這神奇的指針到底在靜態(tài)的狀態(tài)下是多大?我們前面討論過,指針的值是用來標識對象的。所以當我們只需標識256個對象是,指針只需要8位就足夠讓這個256個對象的編號不重復了;但當需要標識65535個對象時,我們就需要16位才能保證所有的對象不重復;更近一步當我們需要40多億個對象的時候我們至少需要32位的長度來保證;以此類推當大于40億的時候我們就需要大于32位的長度來保證,根據磚家們的考證我們其實用128位就可以標識盡這世間萬物。可是搞計算機的,尤其是搞c的都精打細算日子過慣了。舍不得啊,當年16位cup寄存器長度20位尋址長度這種事情都能干出來,現在還幻想著直接上128位的指針,貌似路漫漫啊。
閑話少敘,一個指針的大小到底是多少呢?這個問題貌似簡單,可是從來都不曾簡單過。就從最常用的x86系列cpu來說都是因時而異。更遑論其他系列的cpu。在x86的世界里我用過near來表示只有16位的指針,用far來表示過20位的指針,用huge來表示過32位的指針,至于現在嘛,咳咳,看你的編譯器定義。偷巧的記憶方式是在32位的編譯器下一般是32位,在64位的編譯器下一般是64位。可是這些并沒有涉及到什么內存擴展技術,不然如果涉及到那些,你還得老老實實的去參考編譯器的實現。不然是要吃大虧的。每每想到此就感覺還是解釋語言省事省腦細胞啊。
指針的大小解釋過了,那么指針的步進又當如何理解呢?在Pascal里面好理解,因為Pascal里面有一個專門的inc函數幫助我們已經處理掉了,可是c里面從來都是什么事兒都得自己干,那么如何干呢?指針引用的對象亂七八糟,其小到引用一個字節(jié),其大到引用整個內存空間甚至硬盤空間,他的下一個引用對象的位置當如何確定呢?
我們知道指針都是要指向一個具體對象的,而每一個對象的大小我們都是知道的,ok,這樣處理就簡單了。想想如果直接給指針的地址加上這個對象的大小不就成功的越過了這個對象么?既然越過了所引用的對象不就步進成功了么?不錯確實成功了,可是比較繁瑣,而且機械。有沒有簡單一點的辦法呢?有,這么機械且繁瑣的事兒就讓編譯器去做吧,反正只要告知了編譯器指針所引用的類型,編譯器就能在編譯期間計算錯類型的的大小,只要再定義一個步進符號,編譯器就能夠把這個事兒給辦了。++前進,--后退如何?簡單明了。好,那就這么定了,c的指針的步進就這么定下來了成了標準。這看起來似乎很完美。可是有人說了,如果知道所引用的對象的類型固然好辦,那要是不知道所引用的對象的類型呢?不知道類型的步進對編譯器來說確實難辦,于是這個問題就留給了寫這段代碼的人,因為寫的人總是知道指針所引用的對象的啊,如果寫這段程序的人都不知道,那就只好問上帝了。嘿嘿,挺好,問上帝。不信你問問編譯器,他肯定拒絕給你假設(Pascal對無類型指針也是沒法處理的,不厚道的偷著樂一下)。
指針的基本概念和基本用法都說完了,那么我來看看指針這個玩意兒到底能干什么?指針其實什么都不能干除了能夠引用對象J.有所謂重劍無鋒,大巧不工,各位看官請看我在其他章節(jié)給你嘗試著舞舞這柄重劍。
?
總結
- 上一篇: 人才数据报告不会写?指标不明晰?这套人力
- 下一篇: 最大赢家!TCL X10获SID 202