看板 C_and_CPP 關於我們 聯絡資訊
別再寄私信給我了,我已建議一些書, 找不到相關說明,或沒畫圖的,該再找一些書, 再不然,請善用你手邊 VS 逐步偵錯功能, 或發表出來讓其他版友有機會為你服務, BBS 畫記憶體配置圖真不是件容易的事.. ※ 引述《kswiss11 (kswiss)》之銘言: : { : *p1=(char*)malloc(16); : strcpy(*p1, "Hello"); : } : void main() : { : char*p=NULL; Var. p ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ Addr │0x12│ │ │ │ │ │ │ │ │ │ │ ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ Value │ 0 │ │ │ │ │ │ │ │ │ │ │ └──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴ : printf("%p\n", &p); 0x12 (address of pointer) : test(&p); 呼叫時,記憶體再配一個新的 p1,裡面存 p 之位址值,開始進入副函式 void test(char** p1) Var. p p1 ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ Addr 0x12│... │ │?? │ │ │ │ │ │ │ │ ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ Value │ 0 │... │ │0x12│ │ │ │ │ │ │ │ └──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴ { *p1=(char*)malloc(16); /* equ. below lines. */ char * t = (char*)malloc(16); /* (1) */ * p1 = t; /* (2) */ (1) char* t = (char*)malloc(16); t 指向新配置 16 個空間之開頭 Var. p p1 t t+1 t+2 ... t+15 ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ Addr 0x12│... │ │?? │... │0x80│0x81│0x82│... │0x8f│ │ ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ Value │ 0 │... │ │0x12│... │??? │?? │ ?? │... │ ?? │ │ └──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴ (2) *p1 = t; 將 t 之位址,設給 (p1 指向記憶體位址) 之內容 Var. p p1 t t+1 t+2 ... t+15 ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ Addr0x12│... │ │?? │... │0x80│0x81│0x82│... │0x8f│ │ ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ Value0x80│... │ │0x12│... │????│?? │ ?? │... │ ?? │ │ └──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴ strcpy(*p1, "Hello"); 將 (p1 指向位置) 指向位置,設成 'H' 'E' 'L' 'L' 'O' '\0' Var. p p1 t t+1 t+2 ... t+16 ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ Addr0x12│... │ │?? │... │0x80│0x81│0x82│... │0x8f│ │ ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ Value0x80│... │ │0x12│... │'H' │'E' │ 'L'│... │ ?? │ │ └──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴ 0x80 'H' , 0x81 'E', 0x82 'L', 0x83 'L', 0x84 'O', 0x85 '\0' 0x86~0x8f ???? } 回到主程式後 Var. p ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ Addr0x12│... │ │ │... │0x80│0x81│0x82│... │0x8f│ │ ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ Value0x80│... │ │ │... │'H' │'E' │ 'L'│... │ ?? │ │ └──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴ : printf("%s\n", p); 輸出 p 所指向位置之字串 從 0x80 開始輸出 'H', 一直輸出到 '\0',便輸出 "HELLO" : } 最後加上 free(p); p 內容雖仍不變,但其指向記憶體已不可使用 Var. p ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ Addr0x12│... │ │ │... │0x80│0x81│0x82│... │0x8f│ │ ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ Value0x80│... │ │ │... │??? │??? │ ???│... │ ?? │ │ └──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴ 字串 / 陣列 / 指標 本身便不好理解, 加上 sub_function 實際傳遞機制使得問題更加混亂, 此處確實不好第一次學習就理解,你的書沒有,才跟你說多找幾本書。 ---- 補原 po 於推文中的問題, *p=(char*)malloc(16);不就等於p=(char**)malloc(16);嗎?? 如果改成p=(char**)malloc(16); 然後strcpy(*p, "Hello"); 執行後會出現異常,為什麼??? 那兩行並不相等。 char **p; p = (char**)malloc(16); 這段寫法很危險,想想 malloc 較為一般性的寫法為何 資料型態 *p; p = (資料態型 *)malloc(sizeof(資料型態) * 配置個數) malloc 裡面實際要放的是,「總共記憶體需求量」。 ---- 以 char *p1 而言, char *p1; p1 = (char*)malloc(sizeof(char) * 16); 這裡是配置一個「一維字元陣列,陣列大小有 16 個元素」 也因為每個字元所佔記憶體大小為 1 , 所以 sizeof(char) 都不寫。 ---- 再看 char* *p1, char* *p1; p1 = (char* *)malloc(sizeof(char*) * 16); 這和推文問得一樣,只是把 * 分開一點,所以看起來怪怪的。再看一次公式 資料型態 *p; p = (資料態型 *)malloc(sizeof(資料型態) * 配置個數) 現在資料型態是 char*, pointer to char, 配置出來的是 「一維指標陣列」,p 本身是陣列, 陣列元素裡面放的是一堆「位址值」,因為資料型態是 pointer to char, 那 sizeof(char *) 多大? 這是另一個討論很久的問題,但你現在可不用知道,只需要知道, 1. sizeof(...) 不要省 2. char** p = (char**)malloc(...) 出來的是指標陣列 3. char* p = (char*)malloc(...) 出來的是字元陣列 4. char*** p = (char***)malloc(...) 出來的還是指標陣列 其他的,不要再讚牛角下去了。 -- YouLoveMe() ? LetItBe() : LetMeFree(); -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 180.177.78.41
ericinttu:打這一篇應該至少花了一小時. 08/28 01:55
james732:看到圖文並茂就要推了 08/28 01:56
purpose:原PO人好到讓我想哭了,應該也取個外號,冠上好人兩字... 08/28 01:58
james732:那我改成壞人,好人交給原po好了 XD 08/28 02:03
ericinttu:心得感想: 有時候要懂程式需要到刻骨銘心的地步才會真的 08/28 02:05
ericinttu: 懂. 至少我是經歷過無數次的這種才走到這裡08/28 02:06
ericinttu: 但看到現在的自己, 再比對一些強者, 又笑了. 08/28 02:07
ericinttu: 於是, 現在的我, 比較喜歡用功有傻勁的人 XD 08/28 02:08
tropical72:我打到嘴都歪、臉都綠、手都黑了。 08/28 02:05
tonyhsie:推好人 08/28 02:06
purpose:之前在版上衝動想要回篇 NTFS 的問題,打了一兩天差不多八 08/28 02:10
purpose:成內容,用 PCMan ANSI 編輯器存檔再開,發現很多內容被吃 08/28 02:11
purpose:掉,才發覺在BBS打長文章還真他媽有夠不方便 08/28 02:11
tropical72:..我一直在Ctrl+C/Ctrl+V自行編色碼,表格還是用無蝦米 08/28 02:12
tropical72:加上 Insert 切換畫出來的。 XD 08/28 02:12
james732:這一篇文章值 794 Ptt幣 (敬禮) 08/28 02:14
tropical72:寫到一半時,其實很想問大家都怎麼查 malloc/new 出來 08/28 02:15
tropical72:的內容?我是用 偵錯->視窗->記憶體 慢慢 trace.. 08/28 02:16
purpose:怎麼查,就變數監看 + 記憶體視窗 08/28 02:18
tropical72:嗯,看來似乎大多也都這樣,謝謝 p 大回覆。 *^_^* 08/28 02:19
ericinttu:覺得IDE工具不方便的話, 可以自己再寫輸出訊息的工具. 08/28 02:20
ericinttu:我當初學指標, 算是邊trace邊硬記下電腦處理的程序, 然 08/28 02:22
ericinttu:後再經過一段時間, 才真的懂 指,被指,記憶體位址 的東西 08/28 02:23
tropical72:e大聰明多了,我是不斷 printf address 觀察學習的. 08/28 02:25
james732:我是在寫linked-list的時候用監看式拉來拉去突然頓悟XDD 08/28 02:26
purpose:其實這個程式碼的偵錯算可以有技巧,把中斷點設在 test 裡 08/28 02:31
purpose:然後 VC 的監看式,你可以加 p1 &p1 去觀察,重點是開啟 08/28 02:32
purpose:「呼叫堆疊」視窗,用滑鼠輕輕的點 main 兩下,會跳到上個 08/28 02:32
purpose:函數,此時監看式又可以輸入 p 跟 &p 來監看了... 08/28 02:33
purpose:對了,還有監看式 p1,16 直接把 p1 轉成陣列也是有用 08/28 02:34
VictorTom:推好人:) 08/28 02:34
tropical72:p 大方法太好了,省去一堆記憶體trace麻煩.. 08/28 02:41
purpose:最近覺得用 WinAPIOverride32 來監看 API,神器,推薦大家 08/28 02:45
purpose:Linux 上應該沒像這套那麼方便的軟體 08/28 02:45
tropical72:p 大推的真的是神器 http://0rz.tw/2rzVt 一堆公用程式 08/28 03:01
angleevil:厄...會寄信給別人的,真的算傻勁嗎? 有時候先問一下對方 08/28 07:56
angleevil:比較好吧. 08/28 07:57
angleevil:james732加油,請當一生一世的好人 08/28 07:58
bill42362:佛! 08/28 10:25
kswiss11:真的很感謝你 08/28 11:05
final01:linux沒神器 ... 08/28 12:13
littleshan:valgrind 就是神器啊,雖然功能不太一樣 08/28 14:13
james732:我最近都忙著在電影板嘴炮,沒空在這邊當好人 XDDD 08/28 14:48
johnhmj:強推免費的C/C++教學軟體「tropical72 (藍影)」 (∩_∩) 08/28 16:20
james732:推樓上,再推一次這篇 08/28 16:30
purpose:原PO上新聞版面了 08/28 17:50
kswiss11:*p1=(char*)malloc(6)是配置6個指標陣列 08/28 19:21
kswiss11:那每個陣列元素所指向的記憶體總共有多少個byte??? 08/28 19:22
你只知道用動態配置,但卻不知道配置出來的是什麼東西。 上面有給你一個公式了, 資料型態 *p; p = (資料態型 *)malloc(sizeof(資料型態) * 配置個數) 所以 *p1=(char*)malloc(6); 配出來的不是指標陣列,而是字元陣列。 另上面提到了, 全部要寫 *p1 = (char*)malloc(sizeof(char) * 6); sizeof(char) 是「單一元素大小」,6 指的是「元素個數」, 之所以把 sizeof(char) 拿掉 (我認為對初學者不是好作法), 是因為 sizeof(char) 剛好等於 1,也就是單一元素大小。 ※ 編輯: tropical72 來自: 180.177.78.41 (08/28 19:42)
tropical72:!! purpose 大沒提醒我都沒注意到。 08/28 19:43
tropical72:話說補問的問題,不是連記憶體配置圖都畫出來了嗎 = = 08/28 19:50
alongalone:你應該回他..RTFM 跟 STFW... 08/28 23:18
Gilbert0:不推不行了~ 08/29 00:23
ayumiayayaai:太威猛了... kswiss11根本就沒好好看書= = 08/29 03:16
james732:發現板標換了耶,推一下 XDDD 08/29 03:55
myIDis7:推大好人 08/29 04:32
cobrasgo:你人真好(遞卡) 08/29 12:21
cobrasgo:linux的神器就gdb啦… 08/29 12:23
angleevil:我記得james732有兩次上版標 08/29 12:47
james732:一次而已吧! 08/29 13:13
angleevil:鳥哥那次也算 08/29 13:31
james732:那次我不承認 XD 08/29 14:30
sawang:太帥了 XD 08/29 19:32
xatier:t大好人! 08/30 16:37
azter:轉錄至看板 THUMath95 11/28 07:37