網路城邦
上一篇 回創作列表 下一篇   字體:
C語言裏,究竟const加pointer該如何用呢?
2009/01/12 16:38:47瀏覽16703|回應2|推薦0

        const int * p1;

        int const * p2;

        int * const p3;

    p1,p2,p3究竟差別在哪裡呢?這個地方課本也不太講,網路上也有一些奇怪的解釋,我的不一定對,只是一個看法而已。

    解決這個問題前,先知道一下C語言的命名邏輯,如果我沒有記錯,C語言是【前面的】形容【後面的】【後面的優先被compiler處理】,例如:

        int var;

    上述的意思就是:【有一塊記憶體叫var,它的型態是int】,這個基本邏輯知道後,就可以解答前面的問題了。

    另外當一顆星星(pointer)出現的時候,還沒有特別告訴compiler型態,此時就會以預設值替代,一般來說【預設值是ram】,注意有些cpu比較複雜,就不會只有ram這樣單純,可能是internal sramexternal 16bit ram或是external sdram這些比較複雜的可能性發生。

    假設此時用一個16bit addresscpu,有RAM,有FLASH,假設int是指16bit變數,const是指FLASH的空間,注意這不是絕對。

   

    const int * p1;

    有一塊記憶體叫p1....(1)

    (1)這【整個東西】是pointerp1預設RAM...(2)

    (2)這【整個東西】是int...(3)

    (3)這【整個東西】是const

    注意【整個東西】,例如(3)式,它的所謂整個東西,是包含(2)(1)的,其餘類推。

 

    int const * p2;

    有一塊記憶體叫p2....(1)

    (1)這【整個東西】是pointerp2預設放在RAM...(2)

    (2)這【整個東西】是const...(3)

    (3)這【整個東西】是int

   

    int * const p3;

    有一塊記憶體叫p3....(1)

    (1)這【整個東西】是constp3放在flash...(2)

    (2)這【整個東西】是pointer...(3)

    (3)這【整個東西】是int

 

    以一個沒有特別設定的compiler來說

    p1會放在【RAM】內,它指到某個【16bit】的地方,那個地方在【FLASH】。

    p2會放在【RAM】內,它指到【FLASH】內的某個地方,那個地方是【16bit】。

    p3會放在【FLASH】內,它指到的某個【16bit】的地方,那個地方是【RAM】。

    給個結論,p1p2的功能會一樣。

    p3比較特別,放在FLASH內,指到RAM,究竟這樣有什麼用呢?例如有一個動態字串要顯示,很明顯的,內容要放在RAM,程式固定在某個地方抓資料,所以位址存在FLASH內即可,可以省點RAM的空間,或許有人認為才2bytes有什麼好省的,但是如果是顯示多國語言字型,有好多的pointer要存,就有差別了。

   

    所以看一下另一個宣告:

    const int * const p4;

    知道是什麼意思了吧!p4會放在FLASH,它指到的某個16bit的地方,那個地方是flash

    int const * const p5】,所以p5功能同p4

    怎麼用呢?以上面那個多國語言字型為例,一般來說,字型資料是點矩陣資料,必定是放在FLASH內,所以要寫出一個embedded程式可以自由控制變數該放哪裡,要會做這些雜事,不要過度依賴compiler預設動作,那是不可靠的,甚至是兩顆星星以上的pointer都要會,連void*也要會。

    可以想想看,如果字型資料是放在NAND FLASHHDD,甚至是SD CARD中,那該怎麼辦呢?

( 時事評論政治 )
回應 推薦文章 列印 加入我的文摘
上一篇 回創作列表 下一篇

引用
引用網址:https://classic-blog.udn.com/article/trackback.jsp?uid=cchahacaptain&aid=2558760

 回應文章

Steve
回覆
2011/06/12 01:18
對不起,我錯過了這是embedded C.
然而,最重要的論據仍然有效:

- 因為未知pointer會指向甚麼, 所以任何行為都是未定義.
const char* p1; char a='A';
p1 = "hello";
p1 = &a; //行為完全不同於上一行

- p1與p2的特性也不相同

- 你沒有測試求證

- 變數貯存在constant memory還是stack, 對應於機器上的rom和ram, 取決於對pointer的運用而非宣告
彼得鄧(cchahacaptain) 於 2011-06-14 12:40 回覆:
    看過你的回覆後,感覺你對程式了解還太少,發展環境用的也不夠多,也不知道精不精,當然這是成見,希望我看錯了,說不定你是某位精明的駭客,而我只是一個土蛋。
    不要把PC的理所當然映射到所有平台,早期PC也像現在的embedded system一樣,沒這麼多理所當然,我碰過1MB RAM的時代,我手上還有顆20MB的硬碟當紀念,當然比起更早期打卡機的時代,我又算小CASE了。
    你的思想還在區分embedded c/windows c/linux c,而不是有一個結構,這個結構要用甚麼完成?cpu/FPGA?CPU的話,要用哪種CPU,要用哪種環境發展?作業系統,C/CPP/ASM/還是其他語言,如果是C,共通點在哪裡,把不通點獨立出來,如果你做不到這件事,C語言的可攜性就無法實現,你的程式碼將會面臨無止盡的修改與不穩定性,也不會有資源累積這種事,更不會有長時間累積的函式庫,因為寫的程式連移個平台都有問題,怎麼可能累積呢?就要準備加班,現在CPU進步的速度這麼快,移植就是第一個要碰到的問題,要好好用心解決,多看看,多聽聽,我看過有些人的程式就像骰子一樣有機率的問題,這是不應該發生的。
    我寫網頁的目的是把一些一般會碰到,矛盾的,古怪的,我看過的工程師會發生的問題,我知道的就把它寫出來,一般都是時間問題或公司機密,否則我不太會保留我知道的東西,有錯我會接受,我知道的都是芝麻綠豆的東西,linux那麼複雜的東西都沒保留了,我又算甚麼呢?
    我的經驗不多,碰到和我想法牴觸的通常會先問是怎麼回事,不是先以自己部分經驗就開罵,我的語氣比較強硬,得罪的地方請你見諒。

Steve
回覆
2011/06/12 00:47
你的說法在現實中完全錯誤.

Quote:[ 另外當一顆星星(pointer)出現的時候,還沒有特別告訴compiler型態,此時就會以預設值替代,一般來說【預設值是ram】...]

- 不論pointer的宣告為何, 都不能改變所指的記憶體貯存位置. 因為未知pointer會指向甚麼, 所以任何行為都是未定義.

const char* p1; char a='A';

p1 = "hello";

p1 = &a; //行為完全不同於上一行

- flash本身亦是隨機存儲器(RAM)

- 當程序起始時整個程式會放進main memory

對於"const" modifier的特性以我經驗http://www.codeguru.com/cpp/cpp/cpp_mfc/general/article.php/c6967 的說法最為正確

- p1 與p2的特性也不相同

- 的確, const 可以影響資料存在constant memory還是 stack, 但無論如何也是main memory, 即"ram"

- 你活在自己的世界太久了, 亦懶得測試求證

另外我喜歡你的推論
彼得鄧(cchahacaptain) 於 2011-06-14 12:38 回覆:

要罵人前最好先有十足的把握,不然就會像我那篇"香港之旅"一樣的丟臉,把香港罵的一無是處,結果展現的只是我對旅遊的無知,並不是香港有問題,所以我被很多香港同志們臭罵一頓,我都不敢還嘴,還發出道歉聲明,我現在對香港很歉疚,因為我錯罵了,還害的某些人對香港有成見,所以這些文章我都沒有刪除,就是希望之前被我誤導的某些人有機會修正回來,我被罵的很難聽啊,很丟臉,但我不會拿掉,除非UDN關閉或是我再也不要這個blog。

因為我有點看不懂你要講的內容,所以如果講錯了,不要客氣,立刻反應出來。

Q. [不論pointer的宣告為何, 都不能改變所指的記憶體貯存位置. 因為未知pointer會指向甚麼, 所以任何行為都是未定義]
A. 不對,陣列才無法改變位址,陣列的lable和變數命名一樣只是代號,pointer本身是占有一塊記憶體的,有需要也可以型別轉換,除非它是唯讀記憶體,否則當然可以改變,pc的平台會有很多的exception handler,為了就是預防使用者與程式設計師做出了古怪的動作來產生保護,避免破壞掉其他工作,但是是絕對的嗎?不是的,當你在寫driver時需要進入另一個level,此時許多保護就會消失,所以driver寫的爛的,不管是linux還是windows,都會讓整個系統變的很古怪,也未必會產生錯誤。
    程式怎麼會有未知的pointer?程式的宣告出了問題,你連compiler都過不了關,就算是VB,也是varient這個通用型的變數,不會有未知的出現,我真的看不懂你在說甚麼!

Q. [flash本身亦是隨機存儲器(RAM)]
A. 胡說八道!你是聽誰講的,我都不知道從哪裡回應起,好好把spec讀熟,rom/prom/eprom/eeprom/flash,sram/ssram/dram/sdram,HDD/NAND FLASH/CF CARD/SD CARD這些spec讀熟再來扯,至少你也扯個類生物DNA系統來嚇嚇我,我說不定被嚇到了,結果你拿這個我熟到不能再熟的東西來罵我,真奇怪!給你一個功課,sdram(ddr也一樣)如果沒有MMU效能會低落,為什麼?仔細想一想。

Q. [當程序起始時整個程式會放進main memory]
A. 有作業系統的程式來說是的,尤其是程式是儲存在像hdd/nand flash等等非位址線定址的儲存裝置特需要載入動作,或是需要擺脫慢吞吞的flash也需要載入,如果沒有os,程式也沒有很大,就算是pc,也不一定是需要特別的載入動作,電源啟動時,BIOS會先被CPU執行,當BIOS動作完成後,BIOS會把HDD的sector 0的程式碼載入記憶體,接下來就直接把控制權交出,跳到剛才那段程式的第一byte,接下來就可以像一般的embedded system一樣,可以一個迴圈跑全部程式,也可以所有task都執行,靠message互通,只是pc的能力那麼強,周邊那麼複雜,應該不會有人會捨棄windows或linux來自己搞全部的東西,就算是embedded system,現在也都需要作業系統,因為不只需要multi-task,還有許多周邊裝置需要控制,甚至是網路功能,太多了,做不完,一定要有作業系統,不然要累死了。

那個CONST的網頁我看過了,可能我的英文不好,我實在看不出來和我有甚麼牴觸

Q. [const 可以影響資料存在constant memory還是 stack, 但無論如何也是main memory, 即"ram"]
A. 胡說八道!不要做過PC的程式就認為都是這樣,我不講一般embedded system,你猜猜BIOS的程式碼有沒有const,指的有沒有一定是RAM?

Q. [你活在自己的世界太久了, 亦懶得測試求證]
A. 這應該是我問你的話,我也一路解釋下來了,好好想想吧!我不知道你的經驗是甚麼,有些這麼奇怪的歸納,我告訴你我的,我在大學時代就在寫PC的boot loader了,硬體電路經驗有10年以上,CPU部分,從PIC16/17/18,asm/c都用過,8051從陽春的,到turbo的,到f340這麼複雜的,asm,IAR/keil都用過,熟的不得了,keil的rtos也應用在設計的產品上,power pc與RTOS也做過,廠牌我忘了、ARM 7/9,sdt/ads,ASM我很熟,也做過embedded linux for ARM,以前我的主管移植了uCos RTOS,很好用,我也順便學了過來,還有一些工控cpu,DSP 5409也做過,做過jpeg encode/decode,也做過CD PLAYER,不過做不好,因為cd servo motor不清楚怎麼用,也因為這樣才感覺出來聯發科很厲害,還有一些雜七雜八的就不提了,我能夠自己用ORCAD畫出電路,備料,layout因為不熟,就慢多了,但線路該怎麼走我是清楚的,電路板回來後,除了BGA件,都用手工上件,測試,DEBUG,開始建立環境,設計程式,修改EMI也可以,到這個地步,應該不算懶的測試求證了吧!