看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《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
purpose:用心的回覆,love神當之無愧... 10/31 13:36
剛剛發現後面的程式碼跟 j 大的一樣耶 Orz... OP了
nowar100:大大很用心喔 修改了五次文章 XD 10/31 14:09
怕有些錯字會混淆觀念, 所以重看了幾次 @_@ ※ 編輯: loveme00835 來自: 140.121.197.115 (10/31 14:21)
vm6jp6rmp4:多謝love大,板上那麼多高手的解釋,真是令我獲益良多! 10/31 14:57
bill42362:推! 10/31 15:25
james732:就是等你這一篇 XDDDDDD 10/31 15:34
stupid0319:期待下一篇:關於指標的指標的指標 10/31 15:48
diabloevagto:期待如何一次打十個滿天星 10/31 16:26
xatier:推love大用心解說 11/01 18:15
nanowhiter:太用心了 不推不行 12/03 16:08