![]() |
PCDVD數位科技討論區
(https://www.pcdvd.com.tw/index.php)
- 疑難雜症區
(https://www.pcdvd.com.tw/forumdisplay.php?f=34)
- - VC++的幾個問題part05..
(https://www.pcdvd.com.tw/showthread.php?t=257830)
|
|---|
VC++的幾個問題part05..
好久沒來發問囉!!
但這並不代表我偷懶唷~! 只是有關於生計問題的事要忙 所以只好把學習進度延一下了 仍然請諸位高手不吝賜教囉!! 1)假設A為一個陣列 為何cout <<(sizeof A)/(sizeofA[0]) 就可以表示陣列中有多少個元素呢? 2)對指標的基本概念我大概懂了 但為何指標陣列和一般的字元陣列相比,占用的記憶體 會比較小,而且當字串長短變化較大時,指標陣列可節 省更多空間呢? 先感謝大家的寶貴意見囉~! |
1. 假設
int x[5]; cout << sizeof(x[0]) << endl; // output is 4 because size of an integer is 4 bytes cout << sizeof(x) << end; // output is 4 * 5 = 20 bytes. 4 bytes per each int element and total has 5 elements SO cout << sizeof(x) / sizeof(x[0]) << endl; //prints 5 (elements) because of 20 / 4 2. 不會解釋 |
回覆: VC++的幾個問題part05..
好久不見啦~
1.陣列的長度 / 個別元素的長度,不就是陣列的元素的個數了嗎? 2. "指標陣列和一般的字元陣列相比,占用的記憶體會比較小"...我猜你大概是指「字串(char *)為什麼比字元陣列節省記憶體」吧(不是指標陣列)?! 如果要處理的字串長度變化大時(例如每個人的通訊地址),若是使用字元陣列,你必需要宣告一個「足夠大」的陣列,以應付各種可能(也許有人連太陽系地球都寫進去),那麼不但這個長度不好拿捏,且若是填入的字串很短,那麼豈不浪費剩餘的空間?簡單地說,就是「彈性差」,但是「效率高」,因為它在編譯期就知道要配置多大的記憶體空間了(好比你出去玩之前就先跟飯店訂好房間,那麼你一到目的地後就可以馬上下榻;若是你到了飯店再問有沒有空房,櫃臺再去查電腦,然後再告訴你房間號碼,這樣自然是比較慢的了)! 反之,若是使用字串,那就會在程式被執行時才去尋找一個可用的、連續的記憶體空間來放置這個字串,所以它的「彈性高」,但「效率差」(就好比你出發去玩之前不先找飯店訂房間,到了目的地之後再去找;這間飯店沒有房了再找另一間,直到找到為止)!這裡的彈性,指的就是「浪費記憶體的程度」囉! |
回覆: 回覆: VC++的幾個問題part05..
引用:
------------------------------------------------------------------ 真的好久不見囉~又要麻煩大大線上教學了 1)容小弟囉嗦一點,我舉個例子好了 char* PP[]={ "Merry Christmas", "Happy Birthday", "Happy New Year" }; int num=(sizeofPP)/(sizeofPP[0]); 在以上敘述中小弟有幾個問題: (a)在以上陣列中,是否佔用了3個不同記憶體位置來儲存這3個 不同的字串? (b)PP[0]是否單指"Merry Christmas"這個字串?,如果是, 為何 (sizeofPP)/(sizeofPP[0]) 就可代表整列字串的元素個數? 這3個字串不是都不一樣長,佔用的位元數也都不一樣嗎? 2)嗯...我有一點被搞混了 大大你所謂的字串陣列是不是指像這樣 char* PP[]={ "Merry Christmas", "Happy Birthday", "Happy New Year" }; 這不是"指標型態的字串陣列"嗎? 而字元陣列是不是像這樣 const int MAX=100; char QQ[MAX]="Hello!"; 但是不是所有字串陣列都會用指標表示 所以大大你的意思是說"宣告為指標型態的字串陣列會比字 元陣列來得有彈性是嗎"? 最近一直在指標陣列這邊繞啊繞的 感覺越繞越迷糊.... |
指標是C/C++難學的一環,也是它強大的一環。一開始會搞不清楚是很正常的,唯有多練多思考囉!
1)其實 char* PP[] 並非真的存入"3個字串",而是存入"3個字元指標(就是指字串)",所以PP[0]也是一個指標而已,而不是真的一個字串。用一個指標來代表字串的原因在於,C/C++中並沒有內建"字串"這種資料型態(C++的標準類別庫中有,但仍然不是"內建"資料型態),所以用指向字元的指標來代表一個字串的起始位址,從這個位址起到第一個'\0'為止,視為一個字串。我就延伸你的例子來說明: char* PP[]={ "Merry Christmas", "Happy Birthday", "Happy New Year" }; int num=(sizeof(PP))/(sizeof(PP[0])); cout << "sizeof(PP) : " << sizeof(PP) << endl; cout << "sizeof(PP[0]) : " << sizeof(PP[0]) << endl; cout << "Element count : " << num << endl; 執行之後,你會發現 sizeof(PP) 是 12, sizeof(PP[0]) 是 4,而元素數量是 3。關鍵在 sizeof(PP[0]) 上,這裡得到"在這個系統中指標所佔的記憶體大小(別忘了,指標也是一種資料型態,也佔記憶體,它所代表的值就是某個記憶體位址)",在windows & linux 上都是 4 個 bytes(我不清楚這是因 OS 還是硬體架構而異),所以這個「指標陣列」一共 12 個 bytes, 所以算下來可以得知有 3 個指標,也就是 3 個字串。 2) char* PP[]={ "Merry Christmas", "Happy Birthday", "Happy New Year"}; 這個就是一個字串陣列呀!和上面提到的一樣,C/C++沒有內建字串資料型態,所以用"指向字元的指標"來代表一個字串的開頭,再以第一個'\0'作為結尾;所以與其說這是一個"指標型態的字串陣列",不如說是"C風格的字串陣列"!因為在C++中,使用"String"這種class 來替代 char* 是比較好的解決方案。至於"彈性"的問題,使用 char* 的彈性是比 char[size] 來得高,因為這個 size 在編譯時就要決定了;但是"彈性"的需求也是視狀況而定,若是要處理的資料長度變動不大,使用 char[size] 會是比較有效率的作法(因為OS尋找可用的記憶體空間也是需要花費一些時的)。 |
引用:
------------------------------------------------------------------ 嗯...稍微有點懂,但好像還差那麼一點 請容小弟再發個問 就以相同的例子 1)大大您說 char* PP[] 並非真的存入"3個字串", 那麼是否是存入"3個記憶體儲存位置,然後這3個位置再分別指向 這3個不同字串呢?" 2)PP[0]也是一個指標,那麼它是否指向"Merry Christmas"這個字串? 如果不是,那pp[0]到底是什麼? 那有pp[1],pp[2]這玩意嗎? 3)這陣列佔用了12 byte的"容量",這"容量"可以自己算嗎? 4)指標是記憶體的儲存位置,那麼不管它指向的內容(也許是幾個字母, 數字甚至是冗長的字串)為何,都是佔用4byte嗎? 這些對小弟來說還是蠻不了解的,還望大大多多海涵,能再給小弟我 一些寶貴的意見,感謝您唷 |
呵呵,正所謂「教學相長」,幫你釋疑的同時,我也可以趁此驗證我的觀念有無漏洞,有問題的話別客氣,提出來一起討論囉!
1) char* PP[] 的確只是存入 3 個指向字串的指標,從宣告上就可以看得出來了!這 3 個指標存著 3 個記憶體位址,指向字串。 2)既是字串(或說字元指標)的陣列,裡頭儲存的東西自然就不會是別的囉! PP[0] 的確是指向某個字串的指標,這個陣列中的其它元素亦是如此。 3)C/C++所提供的基本陣列型態,並沒有記錄本身長度的功能(C++的標準類別庫所提供的陣列物件似乎是有的...)。所以一個陣列的長度,就要靠某個變數來記錄了!但是字串不需要刻意去記這個長度,因為字串一定以'\0'結尾,所以只需去判斷這個結束字元,就可以讀取整個完整字串了。 4)沒錯,指標所記錄的資料就是某個記憶體"位址",無論這個指標所指向的資料為何,皆是如此。 |
引用:
------------------------------------------------------------------ 感謝大大這麼詳細的說明 小弟聽大大一席話 雖不敢說已豁然開朗,打通任督二脈 但至少已無墜五里霧中的感覺 但關於第四點,小弟仍有不解之處: 那麼,依這個例子來看,這個"位址"所占用的位元數 就是4 byte囉?那不管此位置指向的內容為幾百字的字串 或是只有一個單字,容量都是4byte?如果是的話,為什麼不管 位址指向的內容再怎麼變都是4byte呢? 還是我把"位址"跟"位元數"弄混了呢? 請大大再次指導囉~ |
你是否對於"指標指向的資料長度不一,卻又同樣只佔 4 bytes"感到疑惑呢?
其實詳細地說,指標記錄著某個"位址",而這個"位址"只是代表著某一"段"記憶體的開頭,裡頭存放著某些資料,舉例來說 : int a = 10; int *p = &a; 假設目前 a 在記憶體中的位址是 1000,那麼 p 目前的值就是 1000。因為一個在32 位元機器的 int 上是 4 bytes,所以接下來的1001, 1002, 1003就是這個變數 a 所佔用的空間,裡頭存放著 10, 指標 p 只是指向 1000 這個位址。當程式透過 p 來讀取變數 a 的值時,系統會讀取從 p 所指向的位址開始之後的 4 bytes (1000, 1001, 1002, 1003)的資料,並把它傳給程式。指標就像是一個標籤,記著記憶體中的某個位址,而這個位址之後多少 bytes 是屬於這個資料的,就看指標所指向的型態了:若是 int 指標,那麼指向位址後的 4 bytes(或 2 bytes,在 16 位元的機器上)就是這一個 int 的值;若是 float 指標,那麼指向位址後的 4 bytes 就是一個 float 的值。指向char 的指標就比較不同,從"指標指向的位址起"至"第一個'\0'出現的位址"止,是一個字串的值。 這樣解釋明白了嗎?;) |
有時候pointer跟array是可以混著用,
compiler會自動幫你處理好,如: char p1[]="01234"; char* p2="01234"; cout<< p1 << " " << p2 <<endl; cout<< p1[0] << " " << p2[0] <<endl; 前後都會有相同的輸出 : 01234 01234 0 0 cout<< sizeof(p1) << " " << sizeof(p2) <<endl; 但這會輸出什麼呢? 答案是: 6 4 sizeof(p1) 等於 6: 因為 p1 是個array,內容為 "01234" + '\0' 共六個 byte 而 sizeof(p2) 等於 4: 因為 p2 是個 pointer ,在 32bits 的電腦架構下就是 32bits==4bytes 至於 p2 指到的內容 "01234\0" 則是用另外的記憶體空間來儲存 |
| 所有的時間均為GMT +8。 現在的時間是01:34 AM. |
vBulletin Version 3.0.1
powered_by_vbulletin 2026。