Re: [問題] 關於指標的指標

看板C_and_CPP作者 (最愛朴素妍)時間15年前 (2010/10/31 13:33), 編輯推噓7(702)
留言9則, 9人參與, 最新討論串3/3 (看更多)
※ 引述《vm6jp6rmp4 (Jun)》之銘言: : 我想延續我之前問的問題,之前的問題我大概了解了,我改寫了一個程式 : #include <stdio.h> : #include <stdlib.h> : #include <string.h> // 以下是多餘的程式碼 : void swap(char *y,int len) : { : char temp; : temp=*(y+len-1); : *(y+len-1)=*(y); : *y=temp; : printf(" yaddress%p\n",&y); : printf("y direction address%p\n",y); : } // 以上是多餘的程式碼 : int main(void) : { : char x[]="Hello"; ┌ 這個 z 定義了卻沒用到 ↓ : char *z=x; : int len=strlen(x); : char **y; ↑ └ 定義了卻沒給初始值, 等一下對他做的所有 dereference 程式碼都是錯誤的 : char temp; : temp=**(y+len-1); : **(y+len-1)=**(y); : **y=temp; : system("pause"); : } 「不懂語意就開始寫程式, 比不懂語法還要糟」,至少後者 編譯器會幫你抓出來, 前者會連錯在哪都不知道. 當定義了一個指標變數如 char* x, 表示你將「藉由 x這個 指標來讀寫一個已經存在的char變數」.  ̄ ̄ char **y 這行可以這樣分成兩部份來看 : char * *y  ̄ ̄ ̄  ̄ 「我將藉由 y 這個指標去讀寫一個已經存在的char*變數」  ̄ ̄ 又因為 *y 取出來的是一個型態為 char*的變數, 此變數本 身也一定要指向一個已經存在的 char 變數 y (型態是 char**) │ └→? (型態是 char*, 必須被配置好且可以讀寫) │ └→ ? (型態是 char, 必須被配置好且可以讀寫) 陣列名稱當指標或者取位址(&)來用的時候, 其值是 array[0] 的位址(= &array[0]), 你的變數 z 剛好就是這個形態, 所 所以可以把 y 指向 z y (型態是 char**) │ └→z (型態是 char*) │ └→ ? (型態是 char, 必須被配置好且可以讀寫) z 本身也已經指向了陣列 x 的第 0 個元素(x[0]), 所以再 把最後一個問號填入 y (型態是 char**) │ └→z (型態是 char*) │ └→ x[0] (型態是 char) 所以你的程式碼還少了 y 的初始化動作 char **y = &z 這 行 ────────────────────────── 以上還只是在驗證一些變數初始值合不合法而已, 下面要討 論你的操作正不正確 y+len-1 // 這行指令算出了一個臨時指標, 裡面的值跟 // y 的值相關, 而 y 的值就是指標 z 的位址 y ┌ y + len - 1 │ ↓ └→z ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │ │ └→ x[0] (型態是 char) 因為 ?的部份是不是已經配置好的變數我們不知道, 所以只 要有對他做 dereference 的動作都是不合法的(就算是配置 好, 裡面的值也不一定是一個char變數的位址). 這行已經錯掉了, 後面的就不必再討論 你要做的運算應該要根據 z的值來做, 比如 z + 1, 實際上 就是 &x[0] + 1 (= &x[ 1 ]), 這樣才會符合你要的結果, 而且 *y 即是取出 z 的值, 所以寫 *y + 1 也是一樣的. y │ └→z = *y = &x[0] z+1 = *y + 1 = &x[0] + 1 = &x[1] │ │ │ │ └→ x[0] x[1] ←──┘ 以下是修改的程式碼(跟前一篇james732大推文的同) : char x[] = "Hello"; int len = strlen( x ); char *z = &x[0]; char **y = &z; char temp; temp = *( *y + len - 1 ); // *( *y + len - 1 ) // = *( x + len - 1) // = *( &x[0] + len - 1 ) // = *&( x[ len - 1 ] ) ← *&對消 // = x[ len - 1 ] *( *y + len - 1 ) = *( *y ); // *( *y ) = *(z) = *&x[0] = x[ 0 ] *( *y ) = temp; puts( x ); 正常人不會寫這種虐待自己的程式碼..因為一旦要定義一個 pointer to non-const pointer, 通常就是要對指到的指標 作改值的動作, 而不是特地為了這種簡單的任務來增加閱讀 的困難度. 我的話會直接忽視 y 這一個實際上沒有作用的 char**變數 , 直接把它的值拿來用, 並且定義兩個具名變數來說明其相 對位置, 再另外寫一個交換的函式, 用函式名稱來說明其意 圖 void swapTwoChars( char *pa, char *pb ) { char temp = *pa; *pa = *pb; *pb = temp; } void main() // 略, y 已經沒有利用價值 char *pLeft = *y, *pRight = *y + len - 1; swapTwoChars( pLeft, pRight ); puts( x ); return 0; } -- ◢████ ◢█ ◢██◣ ◢█ ◢███ ◢█ T-ara版怎麼去 ████◢█████s ~> T-ara ███ █ ◢█歡迎您的光臨 ███████████恩靜智妍孝敏 ███ ██ 素妍居麗寶藍 ████◥██◤ █████ψmakigoto123 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.121.197.115

10/31 13:36, , 1F
用心的回覆,love神當之無愧...
10/31 13:36, 1F
剛剛發現後面的程式碼跟 j 大的一樣耶 Orz... OP了

10/31 14:09, , 2F
大大很用心喔 修改了五次文章 XD
10/31 14:09, 2F
怕有些錯字會混淆觀念, 所以重看了幾次 @_@ ※ 編輯: loveme00835 來自: 140.121.197.115 (10/31 14:21)

10/31 14:57, , 3F
多謝love大,板上那麼多高手的解釋,真是令我獲益良多!
10/31 14:57, 3F

10/31 15:25, , 4F
推!
10/31 15:25, 4F

10/31 15:34, , 5F
就是等你這一篇 XDDDDDD
10/31 15:34, 5F

10/31 15:48, , 6F
期待下一篇:關於指標的指標的指標
10/31 15:48, 6F

10/31 16:26, , 7F
期待如何一次打十個滿天星
10/31 16:26, 7F

11/01 18:15, , 8F
推love大用心解說
11/01 18:15, 8F

12/03 16:08, , 9F
太用心了 不推不行
12/03 16:08, 9F
文章代碼(AID): #1CpF_6sc (C_and_CPP)
文章代碼(AID): #1CpF_6sc (C_and_CPP)