Fw: [問題] 指標的指標問題

看板THUMath95作者 (Yilin)時間8年前 (2015/11/28 07:37), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串1/1
※ [本文轉錄自 C_and_CPP 看板 #1EMIxS0J ] 作者: tropical72 (藍影) 看板: C_and_CPP 標題: Re: [問題] 指標的指標問題 時間: Sun Aug 28 01:52:24 2011 別再寄私信給我了,我已建議一些書, 找不到相關說明,或沒畫圖的,該再找一些書, 再不然,請善用你手邊 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

08/28 01:55, , 1F
打這一篇應該至少花了一小時.
08/28 01:55, 1F

08/28 01:56, , 2F
看到圖文並茂就要推了
08/28 01:56, 2F

08/28 01:58, , 3F
原PO人好到讓我想哭了,應該也取個外號,冠上好人兩字...
08/28 01:58, 3F

08/28 02:03, , 4F
那我改成壞人,好人交給原po好了 XD
08/28 02:03, 4F

08/28 02:05, , 5F
心得感想: 有時候要懂程式需要到刻骨銘心的地步才會真的
08/28 02:05, 5F

08/28 02:06, , 6F
懂. 至少我是經歷過無數次的這種才走到這裡
08/28 02:06, 6F

08/28 02:07, , 7F
但看到現在的自己, 再比對一些強者, 又笑了.
08/28 02:07, 7F

08/28 02:08, , 8F
於是, 現在的我, 比較喜歡用功有傻勁的人 XD
08/28 02:08, 8F

08/28 02:05, , 9F
我打到嘴都歪、臉都綠、手都黑了。
08/28 02:05, 9F

08/28 02:06, , 10F
推好人
08/28 02:06, 10F

08/28 02:10, , 11F
之前在版上衝動想要回篇 NTFS 的問題,打了一兩天差不多八
08/28 02:10, 11F

08/28 02:11, , 12F
成內容,用 PCMan ANSI 編輯器存檔再開,發現很多內容被吃
08/28 02:11, 12F

08/28 02:11, , 13F
掉,才發覺在BBS打長文章還真他媽有夠不方便
08/28 02:11, 13F

08/28 02:12, , 14F
..我一直在Ctrl+C/Ctrl+V自行編色碼,表格還是用無蝦米
08/28 02:12, 14F

08/28 02:12, , 15F
加上 Insert 切換畫出來的。 XD
08/28 02:12, 15F

08/28 02:14, , 16F
這一篇文章值 794 Ptt幣 (敬禮)
08/28 02:14, 16F

08/28 02:15, , 17F
寫到一半時,其實很想問大家都怎麼查 malloc/new 出來
08/28 02:15, 17F

08/28 02:16, , 18F
的內容?我是用 偵錯->視窗->記憶體 慢慢 trace..
08/28 02:16, 18F

08/28 02:18, , 19F
怎麼查,就變數監看 + 記憶體視窗
08/28 02:18, 19F

08/28 02:19, , 20F
嗯,看來似乎大多也都這樣,謝謝 p 大回覆。 *^_^*
08/28 02:19, 20F

08/28 02:20, , 21F
覺得IDE工具不方便的話, 可以自己再寫輸出訊息的工具.
08/28 02:20, 21F

08/28 02:22, , 22F
我當初學指標, 算是邊trace邊硬記下電腦處理的程序, 然
08/28 02:22, 22F

08/28 02:23, , 23F
後再經過一段時間, 才真的懂 指,被指,記憶體位址 的東西
08/28 02:23, 23F

08/28 02:25, , 24F
e大聰明多了,我是不斷 printf address 觀察學習的.
08/28 02:25, 24F

08/28 02:26, , 25F
我是在寫linked-list的時候用監看式拉來拉去突然頓悟XDD
08/28 02:26, 25F

08/28 02:31, , 26F
其實這個程式碼的偵錯算可以有技巧,把中斷點設在 test 裡
08/28 02:31, 26F

08/28 02:32, , 27F
然後 VC 的監看式,你可以加 p1 &p1 去觀察,重點是開啟
08/28 02:32, 27F

08/28 02:32, , 28F
「呼叫堆疊」視窗,用滑鼠輕輕的點 main 兩下,會跳到上個
08/28 02:32, 28F

08/28 02:33, , 29F
函數,此時監看式又可以輸入 p 跟 &p 來監看了...
08/28 02:33, 29F

08/28 02:34, , 30F
對了,還有監看式 p1,16 直接把 p1 轉成陣列也是有用
08/28 02:34, 30F

08/28 02:34, , 31F
推好人:)
08/28 02:34, 31F

08/28 02:41, , 32F
p 大方法太好了,省去一堆記憶體trace麻煩..
08/28 02:41, 32F

08/28 02:45, , 33F
最近覺得用 WinAPIOverride32 來監看 API,神器,推薦大家
08/28 02:45, 33F

08/28 02:45, , 34F
Linux 上應該沒像這套那麼方便的軟體
08/28 02:45, 34F

08/28 03:01, , 35F
p 大推的真的是神器 http://0rz.tw/2rzVt 一堆公用程式
08/28 03:01, 35F

08/28 07:56, , 36F
厄...會寄信給別人的,真的算傻勁嗎? 有時候先問一下對方
08/28 07:56, 36F

08/28 07:57, , 37F
比較好吧.
08/28 07:57, 37F

08/28 07:58, , 38F
james732加油,請當一生一世的好人
08/28 07:58, 38F

08/28 10:25, , 39F
佛!
08/28 10:25, 39F

08/28 11:05, , 40F
真的很感謝你
08/28 11:05, 40F

08/28 12:13, , 41F
linux沒神器 ...
08/28 12:13, 41F

08/28 14:13, , 42F
valgrind 就是神器啊,雖然功能不太一樣
08/28 14:13, 42F

08/28 14:48, , 43F
我最近都忙著在電影板嘴炮,沒空在這邊當好人 XDDD
08/28 14:48, 43F

08/28 16:20, , 44F
強推免費的C/C++教學軟體「tropical72 (藍影)」 (∩_∩)
08/28 16:20, 44F

08/28 16:30, , 45F
推樓上,再推一次這篇
08/28 16:30, 45F

08/28 17:50, , 46F
原PO上新聞版面了
08/28 17:50, 46F

08/28 19:21, , 47F
*p1=(char*)malloc(6)是配置6個指標陣列
08/28 19:21, 47F

08/28 19:22, , 48F
那每個陣列元素所指向的記憶體總共有多少個byte???
08/28 19:22, 48F
你只知道用動態配置,但卻不知道配置出來的是什麼東西。 上面有給你一個公式了, 資料型態 *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)

08/28 19:43, , 49F
!! purpose 大沒提醒我都沒注意到。
08/28 19:43, 49F

08/28 19:50, , 50F
話說補問的問題,不是連記憶體配置圖都畫出來了嗎 = =
08/28 19:50, 50F

08/28 23:18, , 51F
你應該回他..RTFM 跟 STFW...
08/28 23:18, 51F

08/29 00:23, , 52F
不推不行了~
08/29 00:23, 52F

08/29 03:16, , 53F
太威猛了... kswiss11根本就沒好好看書= =
08/29 03:16, 53F

08/29 03:55, , 54F
發現板標換了耶,推一下 XDDD
08/29 03:55, 54F

08/29 04:32, , 55F
推大好人
08/29 04:32, 55F

08/29 12:21, , 56F
你人真好(遞卡)
08/29 12:21, 56F

08/29 12:23, , 57F
linux的神器就gdb啦…
08/29 12:23, 57F

08/29 12:47, , 58F
我記得james732有兩次上版標
08/29 12:47, 58F

08/29 13:13, , 59F
一次而已吧!
08/29 13:13, 59F

08/29 13:31, , 60F
鳥哥那次也算
08/29 13:31, 60F

08/29 14:30, , 61F
那次我不承認 XD
08/29 14:30, 61F

08/29 19:32, , 62F
太帥了 XD
08/29 19:32, 62F

08/30 16:37, , 63F
t大好人!
08/30 16:37, 63F
※ 發信站: 批踢踢實業坊(ptt.cc) ※ 轉錄者: azter (220.132.206.140), 11/28/2015 07:37:33
文章代碼(AID): #1MMEa_QL (THUMath95)