字體:小 中 大 | |
|
|
2008/07/30 18:13:57瀏覽27365|回應1|推薦1 | |
int BombLimitSec[3] = {5, 10, 15}; void BomberCounter(int i) { static int up_count=0; if(i < 3) { if(++up_count == BombLimitSec[i]) { bomb_explore = 1; } } } 上述範例可以看出,炸彈的爆炸計時,只有5,10,15秒三種,麻煩來了,如果此時BombLimitSec[]這個陣列放在【動態記憶體】,如果程式有問題,是有可能被不小心改到的,所以我們可以要求compiler,特別注意這筆數值有沒有人誤寫到,並同時把它放到【唯讀記憶體】,這樣便會安全很多,而這個要求,就是const這個關鍵字。 const int BombLimitSec[3] = {5, 10, 15}; 一般解釋都喜歡講成"如果不小心改到,所以const有用",說實話,這是很虛弱的解釋的,一個正確的程式怎麼會有"不小心改到"這種事發生呢?如果我程式內直接使用pointer來改,const內容也是照改不誤,是擋不住的; 此時又有人會說啦!現代的cpu加上現代作業系統,如Linux,WinXP,Vista等,有記憶體保護,是沒辦法改到const內容的,說實話,這種解釋也是毫無用處,當誤改發生時,系統中斷了程式執行,那這個程式也沒在走了,有個屁用呢?如果這種錯誤是偶發性,是導因於太空中某顆高速粒子正好掉在這台電腦上,那還可以利用這種機制重新開機,可是如果根本是程式寫錯,電路做錯,只要走到這裡就會完蛋,那保護了這個const又有什麼用處呢? 當然如果程式沒有任何bug,電路也非常穩定,有沒有加const,個人是覺得沒有很大的差別的。 但是在embedded system中,甚至是single chip(小型MCU),差別可大了,原因很簡單,問題就出在【動態記憶體(RAM)】與【唯讀記憶體(ROM or Flash)】容量大小差很多。 embedded system可能還好,因為RAM與ROM也相當的大,可是single chip就不一樣了,8k的flash與256bytes的RAM,還可能更小,用起來可相當的吃緊,仔細觀察一下大家周圍的電表、除濕機、冷氣機、微波爐等產品,大致上都是這類CPU做出來的,先暫時別管程式是否有效率,先把不耗腦袋的佔用移除再說,這個時候,const就非常的有用。 如果我們做出一個宣告: long var=100; 這時該有一種認知,var與100這兩個東西一定存在在整個電路的某個地方,而且這個地方一定可以控制的到。 答案是var擺在RAM,100放在ROM,至於放在哪裡?是compiler根據整個程式大小、最佳化等,東算西算決定放在這個位置。 此時又有一個問題出現了,上面的描述在使用時,100早就已經放在var裡面了,很明顯的,一定有一個東西把100放進去var那個RAM的位置。C-Language程式的進入點是main(),所以在main()之前,一定有一個東西做了很多事,讓C的程式能夠從main()開始順利運行,那個東西,叫做boot loader,換句話說,因為刻意的安排,CPU會先執行boot loader,等所有環境建立完成後,再進入main()。 所以boot loader內有很多參數弄不好,程式是不會正常的,就連static的宣告也是boot loader幫你清掉的,忘了清,裡面就都是隨機值。 當CPU通電開始執行時,依照CPU不同種類,一定固定由某個位置開始抓第一行指令開始執行,boot loader的第一行就放在這裡。 依據CPU的複雜度,如ARM7,9就有專門的boot loader,可以做出很複雜的功能,例如可以用TFTP載入,單純的如8051的compiler:IAR51,因為事情很固定,它會自動幫你加上已經寫好的boot loader。 注意單純並不等於容易,不要隨便劃上等號。 細節部份,如果有機會,另闢章節再說,先知道有這件事就好。 回到const,以一個8k flash, 256bytes RAM的CPU(如8052)來說: char array[]={1,2,3,4,5,6}; flash裡面已經放了array的內容,因為上述的寫法是一個有預設值的動態陣列,所以boot loader會把array的內容重新放進RAM後再進入main(),如果今天我們只是把array[]當成常數table存取,那RAM的6個bytes就白白浪費了,這是很可怕的事,因為總共只有256bytes,就是0.25K。 一個程式一定有不少table或字串要宣告,尤其是還有function table,沒多久RAM就會被榨乾,到時也不用做了。 但如果換成 const char array[]={1,2,3,4,5,6}; 此時array[]就只有放在flash內了,當然存取時就是存取flash,當然每種compiler都會提供不同的keyword來指定擺放的位置,甚至可以強制指定要放在哪裏,但const是C language所定義,雖然只能指定唯讀區,但可攜性比較高。 不過要注意,當flash與RAM存取速度一樣時(一般MCU大致是如此),這樣是OK沒有問題,但如果是如ARM7的系統,或是TI DSP 54xx,使用外掛flash,當你在存取flash時,因為flash存取速度本來就慢,會發現程式變的好慢,偷雞不成蝕把米,這時還是把它放進RAM裡面去吧!就是把const拿掉,反正ARM系統的RAM一般都加的很大。 不過要小心,因為可攜性導致的豬羊變色,那邊的好處,攜過來就變壞處了,const就是一個很容易發生的例子。 要注意const不是一定絕對放在flash內,完全是看user怎麼搞而定,使用MCU一定要會定義記憶體區塊,不會定義就可能面臨怪事發生,compiler編譯整個程式時,會依據這些資訊,把整體空間計算好,會把這些空間(如static的RAM區域)的開始結束define成一個符號,而boot loader便依據這樣的資訊把環境建好,只要能讓程式正常運作即可,如果有記憶體的問題,看compiler產生的map檔,通常都會有答案,記得把這樣的option打開。
|
|
( 興趣嗜好|電腦3C ) |