作者loveme00835 (最愛朴素妍)
看板C_and_CPP
標題Re: [自刪] 關於指標的指標
時間Sun Oct 31 13:33:54 2010
※ 引述《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